diff --git a/build/lib/highcharts/__init__.py b/build/lib/highcharts/__init__.py
new file mode 100644
index 0000000..eacf192
--- /dev/null
+++ b/build/lib/highcharts/__init__.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+from .version import version_info, __version__
+
+from .highcharts.highcharts import Highchart
+from .highmaps.highmaps import Highmap
+from .highstock.highstock import Highstock
+
+from . import ipynb
diff --git a/build/lib/highcharts/highcharts/__init__.py b/build/lib/highcharts/highcharts/__init__.py
new file mode 100644
index 0000000..8ca57d6
--- /dev/null
+++ b/build/lib/highcharts/highcharts/__init__.py
@@ -0,0 +1 @@
+from .highcharts import Highchart
\ No newline at end of file
diff --git a/build/lib/highcharts/highcharts/common.py b/build/lib/highcharts/highcharts/common.py
new file mode 100644
index 0000000..ab929fe
--- /dev/null
+++ b/build/lib/highcharts/highcharts/common.py
@@ -0,0 +1,737 @@
+#!/usr/bin/python
+# -*- coding: UTF-8 -*-
+""" Python-Highcharts common.py
+Common Functions For Highcharts
+"""
+from past.builtins import basestring
+import datetime, re
+
+FORMATTER_TYPE_MAPPINGS = {
+ "default": "function() { return this.value }",
+ "date": "function() { return''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + ': '+ this.y; }",
+ "pie": "function() { return ''+ this.point.name +': '+ \
+ this.percentage +' %'; }",
+ "pound_yAxis": "function() { '£' + return this.value }",
+ "pound_tooltip": "function() { return''+ this.x + ': '+ '£' +this.y; }",
+ "percent": "function() { return this.value + ' %' }",
+ "default_tooltip": "function () { return''+ this.series.name + ': ' + this.y; }",
+ "percent_tooltip": "function () { return''+ this.series.name + ': ' + this.y + ' %'; }",
+ "date_percent_tooltip": "function () { return''+Highcharts.dateFormat('%e. %b %Y',this.x) + '
'+ this.series.name + ': ' + this.y + ' %'; }",
+ 'filesize': """
+function() {
+ fileSizeInBytes = this.value;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'date_filesize_tooltip': """
+function() {
+ fileSizeInBytes = this.y;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return ''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + '
' + this.series.name + ': ' + Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'filesize_tooltip': """
+function() {
+ fileSizeInBytes = this.y;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return '' + this.series.name + ': ' + Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'duration': """
+function() {
+ seconds = this.value;
+
+ days = Math.floor(seconds / 86400);
+ seconds = seconds - (days * 86400);
+
+ hours = Math.floor(seconds / 3600);
+ seconds = seconds - (hours * 3600);
+
+ mins = Math.floor(seconds / 60);
+ seconds = seconds - (mins * 60);
+
+ res = "";
+ if(days > 0){
+ res += days + " d ";
+ }
+ if(hours > 0){
+ res += hours + ' hr ';
+ }
+ if(mins > 0){
+ res += mins + ' m ';
+ }
+ if(seconds > 0){
+ res += seconds + ' s ';
+ }
+ return res;
+}
+""",
+ 'date_duration_tooltip': """
+function() {
+ seconds = this.y;
+
+ days = Math.floor(seconds / 86400);
+ seconds = seconds - (days * 86400);
+
+ hours = Math.floor(seconds / 3600);
+ seconds = seconds - (hours * 3600);
+
+ mins = Math.floor(seconds / 60);
+ seconds = seconds - (mins * 60);
+
+ res = "";
+ if(days > 0){
+ res += days + " d ";
+ }
+ if(hours > 0){
+ res += hours + ' hr ';
+ }
+ if(mins > 0){
+ res += mins + ' m ';
+ }
+ if(seconds > 0){
+ res += seconds + ' s ';
+ }
+ return ''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + '
'+ this.series.name + ': ' + res;
+}
+""",
+}
+
+REGEX_LIST = {
+ "re_funct" : re.compile(r'.*function\(.*\)\{.*\}', re.I), #for inputs such as function(xxx){xxx}
+ "re_hcharts" : re.compile(r'.*Highcharts.*', re.I), #for inputs such as highcharts.xxxxx
+}
+
+
+class Formatter(object):
+ """ Base Formatter Class """
+
+ def __init__(self, format=None):
+ ### Choose either from default functions in FORMATTER_TYPE_MAPPINGS using format_type
+ ### or wriet a function in format_string
+ if format:
+ if format in FORMATTER_TYPE_MAPPINGS:
+ self.formatter = RawJavaScriptText(FORMATTER_TYPE_MAPPINGS[format])
+ elif isinstance(format, basestring):
+ self.formatter = RawJavaScriptText(format)
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % basestring)
+
+ def __options__(self):
+ return self.formatter
+
+ def __jsonable__(self):
+ return self.formatter
+
+class ColorObject(object):
+ """ color object """
+
+ def __init__(self, color = None, **kwargs):
+ if not color:
+ color = kwargs
+
+ if color:
+ if isinstance(color, dict):
+ tmp = []
+ for i, item in enumerate(color['stops']):
+ tmp.append([RawJavaScriptText(x) if isinstance(x, basestring) and any([REGEX_LIST[key].search(x) for key in REGEX_LIST.keys()])
+ else x for x in item ])
+ color['stops'] = tmp
+ self.color = color
+ elif any([REGEX_LIST[key].search(color) for key in REGEX_LIST.keys()]):
+ self.color = RawJavaScriptText(color)
+ elif isinstance(color, basestring):
+ self.color = color
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % (basestring or dict))
+ else:
+ self.color = None
+
+ def __options__(self):
+ return self.color
+
+ def __jsonable__(self):
+ return self.color
+
+
+class CSSObject(object):
+ """ CSS style class """
+ ALLOWED_OPTIONS = {}
+ def __init__(self, **kwargs):
+ self.css = kwargs
+
+ for k, v in self.css.items():
+ if isinstance(v, basestring) and any([REGEX_LIST[key].search(v) for key in REGEX_LIST.keys()]):
+ v = RawJavaScriptText(v)
+ self.css.update({k:v})
+
+ def __options__(self):
+ return self.css
+
+ def __jsonable__(self):
+ return self.css
+
+
+class SVGObject(object):
+ """ SVG style class """
+
+ def __init__(self, **kwargs):
+ self.svg = kwargs
+
+ for k, v in self.svg.items():
+ if isinstance(v, basestring) and any([REGEX_LIST[key].search(v) for key in REGEX_LIST.keys()]):
+ v = RawJavaScriptText(v)
+ self.svg.update({k:v})
+
+ def __options__(self):
+ return self.svg
+
+ def __jsonable__(self):
+ return self.svg
+
+
+class JSfunction(object):
+
+ def __init__(self, function = None):
+ if function:
+ if isinstance(function, basestring):
+ self.function = RawJavaScriptText(function)
+ elif isinstance(function, JSfunction):
+ self.function = function
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % basestring)
+
+
+ def __options__(self):
+ return self.function
+
+ def __jsonable__(self):
+ return self.function
+
+
+class RawJavaScriptText:
+
+ def __init__(self, jstext):
+ self._jstext = jstext
+ def get_jstext(self):
+ return self._jstext
+
+
+class CommonObject(object):
+
+ def __init__(self, **kwargs):
+ self.process_kwargs(kwargs)
+
+ def __validate_options__(self, k, v, ov):
+
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def update(self, kwargs):
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), CommonObject):
+ # re-construct input dict with existing options in objects
+ if self.__getattr__(k):
+ if isinstance(v, dict):
+ self.__options__()[k].update(v)
+ else:
+ self.__options__()[k].__options__().update(v)
+ else:
+ self.__options__().update({k:allowed_args[k][0](**v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), ArrayObject):
+ # update array
+ if isinstance(v, dict):
+ self.__dict__[k].append(self.ALLOWED_OPTIONS[k][0](**v))
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].append(self.ALLOWED_OPTIONS[k][0](**item))
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ (isinstance(self.ALLOWED_OPTIONS[k][0](), CSSObject) or isinstance(self.ALLOWED_OPTIONS[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items():
+ self.__dict__[k].__options__().update({key:value})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and (isinstance(self.ALLOWED_OPTIONS[k][0](), JSfunction) or
+ isinstance(self.ALLOWED_OPTIONS[k][0](), Formatter) or isinstance(self.ALLOWED_OPTIONS[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+
+ else:
+ raise OptionTypeError("Not An Accepted Option Type: %s" % k)
+
+ def process_kwargs(self, kwargs):
+
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if self.__validate_options__(k,v,self.ALLOWED_OPTIONS[k]):
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ self.ALLOWED_OPTIONS[k][0] in IDV_OBJECT_LIST:
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % self.ALLOWED_OPTIONS[k])
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Event Class:" % k)
+
+ def __getattr__(self, item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class Events(CommonObject):
+ """ Class for event listener """
+
+ ALLOWED_OPTIONS = {
+ "addSeries": (JSfunction, basestring),
+ "afterPrint": (JSfunction, basestring),
+ "beforePrint": (JSfunction, basestring),
+ "click": (JSfunction, basestring),
+ "drilldown": (JSfunction, basestring),
+ "drillup": (JSfunction, basestring),
+ "load": (JSfunction, basestring),
+ "redraw": (JSfunction, basestring),
+ "selection": (JSfunction, basestring),
+ "afterAnimate": (JSfunction, basestring),
+ "checkboxClick": (JSfunction, basestring),
+ "hide": (JSfunction, basestring),
+ "legendItemClick": (JSfunction, basestring),
+ "mouseOut": (JSfunction, basestring),
+ "mouseOver": (JSfunction, basestring),
+ "show": (JSfunction, basestring),
+ "remove": (JSfunction, basestring),
+ "select": (JSfunction, basestring),
+ "unselect": (JSfunction, basestring),
+ "update": (JSfunction, basestring),
+ "afterBreaks": (JSfunction, basestring),
+ "afterSetExtremes": (JSfunction, basestring),
+ "pointBreak": (JSfunction, basestring),
+ "setExtremes": (JSfunction, basestring)
+ }
+
+class Point(CommonObject):
+ ALLOWED_OPTIONS = {
+ "events": (Events, dict)
+ }
+
+class Position(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+class ContextButton(CommonObject):
+ """ Option class for the export button """
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "enabled": bool,
+ "height": int,
+ "menuItems": NotImplemented,
+ "onclick": (JSfunction, basestring),
+ "symbol": basestring,
+ "symbolFill": basestring,
+ "symbolSize": int,
+ "symbolStroke": basestring,
+ "symbolStrokeWidth": int,
+ "symbolX": [float, int],
+ "symbolY": [float, int],
+ "text": basestring,
+ "theme": NotImplemented,#ThemeObject
+ "verticalAlign": basestring,
+ "width": int,
+ "x": int,
+ "y": int,
+ }
+
+class Back(CommonObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "size": [int, float]
+ }
+
+class Bottom(CommonObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "size": [int, float]
+ }
+
+class Side(CommonObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "size": [int, float]
+ }
+
+class Frame(CommonObject):
+ ALLOWED_OPTIONS = {
+ "back": (Back, dict),
+ "bottom": (Bottom, dict),
+ "side": (Side, dict),
+ }
+
+class Options3d(CommonObject):
+ ALLOWED_OPTIONS = {
+ "alpha": [float, int],
+ "beta": [float, int],
+ "depth": int,
+ "enabled": bool,
+ "frame": (Frame, dict),
+ "viewDistance": int
+ }
+
+class ResetZoomButton(CommonObject):
+ ALLOWED_OPTIONS = {
+ "position": (Position, dict),
+ "relativeTo": basestring,
+ "theme": NotImplemented #ThemeObject
+ }
+
+class DrillUpButton(CommonObject):
+ ALLOWED_OPTIONS = {
+ "position": (Position, dict),
+ "relativeTo": basestring,
+ "theme": NotImplemented #ThemeObject
+ },
+
+class Labels(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": [float, int],
+ "borderWidth": [int, basestring],
+ "color": (ColorObject, basestring, dict),
+ "connectorColor": (ColorObject, basestring, dict),
+ "connectorPadding": [float, int],
+ "connectorWidth": [float, int],
+ "crop": bool,
+ "defer": bool,
+ "distance": int,
+ "enabled": bool,
+ "format": basestring,
+ "formatter": (Formatter, JSfunction, basestring),
+ "inside": bool,
+ "overflow": basestring,
+ "padding": [float, int],
+ "rotation": int,
+ "shadow": [bool, dict], #shadow object
+ "shape": basestring,
+ "softConnector": bool,
+ "staggerLines": int,
+ "step": int,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "textAlign": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ "zIndex": int,
+ }
+
+class Title(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "enabled": bool,
+ "margin": int,
+ "offset": int,
+ "rotation": int,
+ "style": (CSSObject, dict),
+ "text": [basestring, type(None)]
+ }
+
+class Navigation(CommonObject):
+ ALLOWED_OPTIONS = {
+ "activeColor": (ColorObject, basestring, dict),
+ "animation": NotImplemented,
+ "arrowSize": int,
+ "inactiveColor": (ColorObject, basestring, dict),
+ "style": (CSSObject, dict),
+ }
+
+class DateTimeLabelFormats(CommonObject):
+ ALLOWED_OPTIONS = {
+ "millisecond": basestring,
+ "second": basestring,
+ "minute": basestring,
+ "hour": basestring,
+ "day": basestring,
+ "week": basestring,
+ "month": basestring,
+ "year": basestring,
+ }
+
+class Select(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "radius": int,
+ }
+
+class States(CommonObject):
+ ALLOWED_OPTIONS = {
+ "hover": dict,
+ "select": dict,
+ }
+
+class Marker(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "height": int,
+ "lineWidth": int,
+ "lineColor": (ColorObject, basestring, dict),
+ "radius": int,
+ "states": (States, dict),
+ "symbol": basestring,
+ "width": int
+ }
+
+class Halo(CommonObject):
+ ALLOWED_OPTIONS = {
+ "attributes": (SVGObject, dict),
+ "opacity": float,
+ "size": int
+ }
+
+class Hover(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "halo": (Halo, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "lineWidthPlus": int,
+ "marker": (Marker, dict),
+ "radius": int,
+ "radiusPlus": int,
+ "color": (ColorObject, basestring, dict),
+ }
+
+class States(CommonObject):
+ ALLOWED_OPTIONS = {
+ "hover": (Hover, dict),
+ "select": (Select, dict)
+ }
+
+class Tooltip(CommonObject):
+ ALLOWED_OPTIONS = {
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "followPointer": bool,
+ "followTouchMove": bool,
+ "footerFormat": basestring,
+ "headerFormat": basestring,
+ "hideDelay": int,
+ "pointFormat": basestring,
+ "pointFormatter": (Formatter, JSfunction, basestring),
+ "shape": basestring,
+ "valueDecimals": int,
+ "valuePrefix": basestring,
+ "valueSuffix": basestring,
+ "xDateFormat": basestring
+ }
+
+
+class ArrayObject(object):
+
+ def __init__(self, **kwargs):
+ self.data =[]
+ self.process_kwargs(kwargs)
+
+ def __validate_options__(self, k,v,ov):
+
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.data
+
+ def __jsonable__(self):
+ return self.data
+
+ def update(self, kwargs):
+ self.process_kwargs(kwargs)
+
+ def process_kwargs(self, kwargs):
+ temp = {}
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if self.__validate_options__(k,v,self.ALLOWED_OPTIONS[k]):
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ self.ALLOWED_OPTIONS[k][0] in IDV_OBJECT_LIST:
+ if isinstance(v, dict):
+ temp.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ temp.update({k:v})
+ else:
+ temp.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ temp.update({k:v})
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % self.ALLOWED_OPTIONS[k])
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Event Class:" % k)
+ self.data.append(temp)
+
+class PlotBands(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, basestring],
+ "color": (ColorObject, basestring, dict),
+ "events": (Events, dict),
+ "from": [int, float, datetime.datetime],
+ "id": basestring,
+ "label": (Labels, dict),
+ "to": [int, float, datetime.datetime],
+ "zIndex": int
+ }
+
+class PlotLines(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "dashStyle": basestring,
+ "events": (Events, dict),
+ "id": basestring,
+ "label": (Labels, dict),
+ "value": [int, float],
+ "width": int,
+ "zIndex": int
+ }
+
+class Items(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "html": basestring,
+ "style": (CSSObject, dict)
+ }
+
+class Background(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, basestring],
+ "borderColor": (ColorObject, basestring, dict),
+ "innerWidth": int,
+ "outerWidth": int,
+ "outerRadius": basestring,
+ "shape": basestring,
+ }
+
+class Breaks(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "breakSize": int,
+ "from": [int, float],
+ "repeat": int,
+ "to": [int, float],
+ }
+
+class DataClasses(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "from": [int, float],
+ "name": basestring,
+ "to": [int, float],
+ }
+
+class Zones(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "value": [int, float],
+ }
+
+class Levels(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderDashStyle": basestring,
+ "borderWidth": [int, basestring],
+ "color": (ColorObject, basestring, dict),
+ "dataLabels": (Labels, dict),
+ "layoutAlgorithm": basestring,
+ "layoutStartingDirection": basestring,
+ "level": int,
+ }
+
+
+IDV_OBJECT_LIST = [JSfunction, Formatter, Halo, Marker, Labels,
+ Position, Hover, Select, Events, States, ContextButton,
+ CSSObject, SVGObject, ColorObject,
+ RawJavaScriptText, DateTimeLabelFormats]
+
+
+class OptionTypeError(Exception):
+
+ def __init__(self, *args):
+ self.args = args
diff --git a/build/lib/highcharts/highcharts/highchart_types.py b/build/lib/highcharts/highcharts/highchart_types.py
new file mode 100644
index 0000000..c8c241d
--- /dev/null
+++ b/build/lib/highcharts/highcharts/highchart_types.py
@@ -0,0 +1,672 @@
+# -*- coding: UTF-8 -*-
+from past.builtins import basestring
+
+import json, datetime
+from .common import Formatter, Events, Position, ContextButton, Options3d, ResetZoomButton, DrillUpButton, \
+ Labels, Marker, Point, PlotBands, States, Tooltip, Title, Zones, Levels, \
+ JSfunction, ColorObject, CSSObject, SVGObject, \
+ CommonObject, ArrayObject
+
+PLOT_OPTION_ALLOWED_ARGS = {
+ "common": {
+ "animation": bool,
+ "color": (ColorObject, basestring, dict),
+ "cursor": basestring,
+ "dataLabels": (Labels, dict),
+ "enableMouseTracking": bool,
+ "events": (Events, dict),
+ "id": basestring,
+ "index": [float, int],
+ "name": basestring,
+ "point": (Point, dict),
+ "selected": bool,
+ "showCheckbox": bool,
+ "showInLegend": bool,
+ "states": (States, dict),
+ "stickyTracking": bool,
+ "tooltip": (Tooltip, dict),
+ "visible": bool,
+ "xAxis": [int, basestring],
+ "yAxis": [int, basestring],
+ "zIndex": int,
+ "zoneAxis": basestring,
+ "zones": (Zones, dict),
+ },
+ "area": {
+ "allowPointSelect": bool,
+ "connectEnds": bool,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "getExtremesFromAll": bool,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "negativeColor": (ColorObject, basestring, dict),
+ "negativeFillColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": (int,basestring, datetime.datetime),
+ "shadow": [bool, dict], #shadow object
+ "stacking": basestring,
+ "step": bool,
+ "threshold": [int, type(None)],
+ "trackByArea": bool,
+ "turboThreshold": int,
+ },
+ "arearange": {
+ "allowPointSelect": bool,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "getExtremesFromAll": bool,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "negativeColor": (ColorObject, basestring, dict),
+ "negativeFillColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "trackByArea": bool,
+ "turboThreshold": int,
+ },
+ "areaspline": {
+ "allowPointSelect": bool,
+ "cropThreshold": int,
+ "connectEnds": bool,
+ "connectNulls": bool,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "getExtremesFromAll": bool,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "negativeColor": (ColorObject, basestring, dict),
+ "negativeFillColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "threshold": [int, type(None)],
+ "turboThreshold": int,
+ "trackByArea": bool,
+ },
+ "areasplinerange": {
+ "allowPointSelect": bool,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "pointInterval": int,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "turboThreshold": int,
+ "trackByArea": bool,
+ },
+ "bar": {
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": [int, basestring],
+ "colorByPoint": bool,
+ "colors": list,
+ "cropThreshold": int,
+ "depth": [int, float],
+ "edgeColor": (ColorObject, basestring, dict),
+ "edgeWidth": int,
+ "getExtremesFromAll": bool,
+ "groupPadding": [float, int],
+ "groupZPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "linkedTo": basestring,
+ "minPointLength": int,
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPadding": [float, int],
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "pointWidth": int,
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "threshold": [int, type(None)],
+ "turboThreshold": int,
+ },
+ "boxplot": {
+ "allowPointSelect": bool,
+ "colorByPoint": bool,
+ "colors": list,
+ "depth": [int, float],
+ "edgeColor": (ColorObject, basestring, dict),
+ "edgeWidth": int,
+ "fillColor": (ColorObject, basestring, dict),
+ "getExtremesFromAll": bool,
+ "groupPadding": [float, int],
+ "groupZPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "medianColor": (ColorObject, basestring, dict),
+ "medianWidth": [int,float],
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPadding": [float, int],
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "pointWidth": int,
+ "shadow": [bool, dict],
+ "size": [int,basestring],
+ "slicedOffset": int,
+ "startAngle": int,
+ "showInLegend": bool
+ },
+ "bubble": {
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": int,
+ "colors": list,
+ "colorByPoint": bool,
+ "cropThreshold": int,
+ "depth": [int, float],
+ "edgeColor": (ColorObject, basestring, dict),
+ "edgeWidth": int,
+ "getExtremesFromAll": bool,
+ "groupPadding": [float, int],
+ "groupZPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "linkedTo": basestring,
+ "minPointLength": int,
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPadding": [float, int],
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "pointWidth": int,
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "threshold": [int, type(None)],
+ "turboThreshold": int,
+ },
+ "column": {
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": [int, basestring],
+ "colors": list,
+ "colorByPoint": bool,
+ "cropThreshold": int,
+ "depth": [int, float],
+ "edgeColor": (ColorObject, basestring, dict),
+ "edgeWidth": int,
+ "getExtremesFromAll": bool,
+ "groupPadding": [float, int],
+ "groupZPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "linkedTo": basestring,
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "minPointLength": int,
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointPadding": [float, int],
+ "pointRange": int,
+ "pointWidth": [int, float],
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "threshold": [int, type(None)],
+ "turboThreshold": int,
+ },
+ "columnrange": {
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": [int, basestring],
+ "colors": list,
+ "colorByPoint": bool,
+ "depth": [int, float],
+ "edgeColor": (ColorObject, basestring, dict),
+ "edgeWidth": int,
+ "getExtremesFromAll": bool,
+ "cropThreshold": int,
+ "groupPadding": [float, int],
+ "groupZPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "linkedTo": basestring,
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "minPointLength": int,
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointPadding": [float, int],
+ "pointRange": int,
+ "pointWidth": int,
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "threshold": [int, type(None)],
+ "turboThreshold": int,
+ },
+ "errorbar": {
+ "allowPointSelect": bool,
+ "colors": list,
+ "colorByPoint": bool,
+ "cursor": basestring,
+ "depth": [int, float],
+ "edgeColor": (ColorObject, basestring, dict),
+ "edgeWidth": int,
+ "getExtremesFromAll": bool,
+ "cropThreshold": int,
+ "groupZPadding": [float, int],
+ "keys": list,
+ "linkedTo": basestring,
+ "lineWidth": int,
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointPadding": [float, int],
+ "pointRange": int,
+ "pointWidth": int,
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "stemColor": (ColorObject, basestring, dict),
+ "stemDashStyle": basestring,
+ "stemWidth": [float, int],
+ "stickyTracking": bool,
+ "turboThreshold": int,
+ "whiskerColor": (ColorObject, basestring, dict),
+ "whiskerLength": [float, int, basestring],
+ "whiskerWidth": [float, int]
+ },
+ "gauge": {
+ "dial": NotImplemented,
+ "linkedTo": basestring,
+ "negativeColor": (ColorObject, basestring, dict),
+ "overshoot": [int, float],
+ "pivot": NotImplemented,
+ "stickyTracking": bool,
+ "threshold": [int, type(None)],
+ "wrap": bool,
+ },
+ "heatmap": {
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": [int, basestring],
+ "colors": list,
+ "colorByPoint": bool,
+ "colsize": int,
+ "cropThreshold": int,
+ "getExtremesFromAll": bool,
+ "keys": list,
+ "legendIndex": [int, float],
+ "linkedTo": basestring,
+ "rowsize": int,
+ "shadow": [bool, dict], #shadow object
+ "stickyTracking": bool,
+ "turboThreshold": int,
+ },
+ "line": {
+ "allowPointSelect": bool,
+ "connectEnds": bool,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "getExtremesFromAll": bool,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "step": basestring,
+ "turboThreshold": int,
+ },
+ "pie": {
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, basestring],
+ "center": list,
+ "colors": list,
+ "depth": [int, float],
+ "endAngle": [int, float],
+ "ignoreHiddenPoint": bool,
+ "innerSize": [int, basestring],
+ "legendIndex": [int, basestring],
+ "linkedTo": basestring,
+ "minSize": [int, basestring],
+ "shadow": [bool, dict],
+ "showInLegend": bool,
+ "size": [int,basestring],
+ "slicedOffset": int,
+ "startAngle": int,
+ },
+ "scatter": {
+ "allowPointSelect": bool,
+ "colorByPoint": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "threshold": [int, float],
+ "turboThreshold": int,
+ },
+ "series": {
+ "allowPointSelect": bool,
+ "borderWidth": [int, basestring],
+ "connectEnds": bool,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "lineWidth": int,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "spline": {
+ "allowPointSelect": bool,
+ "connectEnds": bool,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "treemap": {
+ "allowDrillToNode": bool,
+ "allowPointSelect": bool,
+ "alternateStartingDirection": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, basestring],
+ "colors": list,
+ "colorByPoint": bool,
+ "cropThreshold": int,
+ "getExtremesFromAll": bool,
+ "interactByLeaf": bool,
+ "keys": list,
+ "layoutAlgorithm": basestring,
+ "layoutStartingDirection": basestring,
+ "legendIndex": [int, float],
+ "levelIsConstant": bool,
+ "levels": (Levels, dict, list),
+ "linkedTo": basestring,
+ "shadow": [bool, dict],
+ "stickyTracking": bool,
+ "turboThreshold": int,
+ },
+}
+
+DATA_SERIES_ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "connectEnds": bool,
+ "connectNulls": bool,
+ "dataLabels": (Labels, dict),
+ "dataParser": NotImplemented,
+ "dataURL": NotImplemented,
+ "drilldown": basestring,
+ "events": (Events, dict),
+ "high": [int, float],
+ "id": basestring,
+ "index": int,
+ "legendIndex": int,
+ "name": basestring,
+ "marker": (Marker, dict),
+ "selected": bool,
+ "sliced": bool,
+ "showInLegend": bool,
+ "stack": basestring,
+ "type": basestring,
+ "visible": bool,
+ "x": [int, float],
+ "xAxis": int,
+ "yAxis": int,
+}
+
+DEFAULT_OPTIONS = {
+
+}
+
+class OptionTypeError(Exception):
+
+ def __init__(self,*args):
+ self.args = args
+
+
+class SeriesOptions(object):
+ """Class for plotOptions"""
+
+ def __init__(self,series_type="line",supress_errors=False,**kwargs):
+ self.load_defaults(series_type)
+ self.process_kwargs(kwargs,series_type=series_type,supress_errors=supress_errors)
+
+ @staticmethod
+ def __validate_options__(k,v,ov):
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def update(self,series_type, **kwargs):
+ allowed_args = PLOT_OPTION_ALLOWED_ARGS[series_type]
+ allowed_args.update(PLOT_OPTION_ALLOWED_ARGS["common"])
+ for k, v in kwargs.items():
+ if k in allowed_args:
+ if SeriesOptions.__validate_options__(k,v,allowed_args[k]):
+ if isinstance(allowed_args[k], tuple) and isinstance(allowed_args[k][0](), CommonObject):
+ # re-construct input dict with existing options in objects
+ if self.__getattr__(k):
+ if isinstance(v, dict):
+ self.__options__()[k].update(v)
+ else:
+ self.__options__()[k].__options__().update(v)
+ else:
+ self.__options__().update({k:allowed_args[k][0](**v)})
+
+ elif isinstance(allowed_args[k], tuple) and isinstance(allowed_args[k][0](), ArrayObject):
+ # update array
+ if isinstance(v, dict):
+ self.__dict__[k].append(allowed_args[k][0](**v))
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].append(allowed_args[k][0](**item))
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(v))
+
+ elif isinstance(allowed_args[k], tuple) and \
+ (isinstance(allowed_args[k][0](), CSSObject) or isinstance(allowed_args[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items():
+ self.__dict__[k].__options__().update({key:value})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+
+ elif isinstance(allowed_args[k], tuple) and (isinstance(allowed_args[k][0](), JSfunction) or
+ isinstance(allowed_args[k][0](), Formatter) or isinstance(allowed_args[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ print(k,v)
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % allowed_args[k])
+
+
+ def process_kwargs(self,kwargs,series_type,supress_errors=False):
+ allowed_args = PLOT_OPTION_ALLOWED_ARGS[series_type]
+ allowed_args.update(PLOT_OPTION_ALLOWED_ARGS["common"])
+
+ for k, v in kwargs.items():
+ if k in allowed_args:
+ if SeriesOptions.__validate_options__(k,v,allowed_args[k]):
+ if isinstance(allowed_args[k], tuple):
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ elif isinstance(v, list):
+ if len(v) == 1:
+ self.__dict__.update({k:allowed_args[k][0](**v[0])})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v[0])})
+ for item in v[1:]:
+ self.__dict__[k].update(item)
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ print(k,v)
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % allowed_args[k])
+
+
+ def load_defaults(self,series_type): # not in use
+ self.process_kwargs(DEFAULT_OPTIONS.get(series_type,{}),series_type)
+
+ def __getattr__(self,item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class Series(object):
+ """Series class for input data """
+
+ def __init__(self, data, series_type="line", supress_errors=False, **kwargs):
+
+ # List of dictionaries. Each dict contains data and properties,
+ # which need to handle before construct the object for series
+ if isinstance(data, list):
+ for item in data:
+ if isinstance(item, dict):
+ for k, v in item.items():
+ if k in DATA_SERIES_ALLOWED_OPTIONS:
+ if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
+ if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
+ if isinstance(v, dict):
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ item.update({k:v})
+ else:
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
+ else:
+ item.update({k:v})
+
+ self.__dict__.update({
+ "data": data,
+ "type": series_type,
+ })
+
+ # Series propertie can be input as kwargs, which is handled here
+ for k, v in kwargs.items():
+ if k in DATA_SERIES_ALLOWED_OPTIONS:
+ if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
+ if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
+ if isinstance(v, dict):
+ self.__dict__.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % DATA_SERIES_ALLOWED_OPTIONS[k])
+
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
diff --git a/build/lib/highcharts/highcharts/highcharts.py b/build/lib/highcharts/highcharts/highcharts.py
new file mode 100644
index 0000000..6262c42
--- /dev/null
+++ b/build/lib/highcharts/highcharts/highcharts.py
@@ -0,0 +1,473 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import unicode_literals, absolute_import
+from future.standard_library import install_aliases
+install_aliases()
+from past.builtins import basestring
+
+from jinja2 import Environment, PackageLoader
+
+import json, uuid
+import re
+import datetime
+import urllib.request, urllib.error, urllib.parse
+import html
+try:
+ # works with older (3.9 and below) versions, throws an exception with newer (3.10 and above) versions
+ from collections import Iterable
+#if an import error change to trying 3.10 and above notation
+except ImportError:
+ from collections.abc import Iterable
+from .options import BaseOptions, ChartOptions, ColorAxisOptions, \
+ ColorsOptions, CreditsOptions, DrilldownOptions, ExportingOptions, \
+ GlobalOptions, LabelsOptions, LangOptions, \
+ LegendOptions, LoadingOptions, NavigationOptions, PaneOptions, \
+ PlotOptions, SeriesData, SubtitleOptions, TitleOptions, \
+ TooltipOptions, xAxisOptions, yAxisOptions, zAxisOptions, MultiAxis
+
+from .highchart_types import Series, SeriesOptions
+from .common import Levels, Formatter, CSSObject, SVGObject, JSfunction, RawJavaScriptText, \
+ CommonObject, ArrayObject, ColorObject
+
+CONTENT_FILENAME = "content.html"
+PAGE_FILENAME = "page.html"
+
+pl = PackageLoader('highcharts.highcharts', 'templates')
+jinja2_env = Environment(lstrip_blocks=True, trim_blocks=True, loader=pl)
+
+template_content = jinja2_env.get_template(CONTENT_FILENAME)
+template_page = jinja2_env.get_template(PAGE_FILENAME)
+
+
+class Highchart(object):
+ """
+ Highcharts Base class.
+ """
+ #: chart count
+ count = 0
+
+ # this attribute is overriden by children of this
+ # class
+ CHART_FILENAME = None
+ template_environment = Environment(lstrip_blocks=True, trim_blocks=True,
+ loader=pl)
+
+ def __init__(self, **kwargs):
+ """
+ This is the base class for all the charts. The following keywords are
+ accepted:
+ :keyword: **display_container** - default: ``True``
+ **offline - default: ``False``
+ If True, download all .js and .css file and put them
+ into the generated .html so it can be viewed offline.
+ """
+ # set the model
+ self.model = self.__class__.__name__ #: The chart model,
+ self.div_name = kwargs.get("renderTo", "container")
+
+ # an Instance of Jinja2 template
+ self.template_page_highcharts = template_page
+ self.template_content_highcharts = template_content
+
+
+ # set Javascript src, Highcharts lib needs to make sure it's up to date
+ self.JSsource = [
+ 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
+ 'https://code.highcharts.com/6/highcharts.js',
+ 'https://code.highcharts.com/6/highcharts-more.js',
+ 'https://code.highcharts.com/6/modules/heatmap.js',
+ 'https://code.highcharts.com/6/modules/exporting.js'
+ ]
+
+ # set CSS src
+ self.CSSsource = [
+ 'https://www.highcharts.com/highslide/highslide.css',
+
+ ]
+
+ self.offline = kwargs.get("offline", False)
+
+ # set data
+ self.data = []
+ self.data_temp = []
+ # Data from jsonp
+ self.jsonp_data_flag = False
+ self.jsonp_data_url_list = [] # DEM 2017/07/27: List of JSON data sources
+
+ # set drilldown data
+ self.drilldown_data = []
+ self.drilldown_data_temp = []
+
+ # javascript
+ self.jscript_head_flag = False
+ self.jscript_head = kwargs.get('jscript_head', None)
+ self.jscript_end_flag = False
+ self.jscript_end = kwargs.get('jscript_end', None)
+
+ # accepted keywords
+ self.div_style = kwargs.get('style', '')
+ self.drilldown_flag = kwargs.get('drilldown_flag', False)
+
+ # None keywords attribute that should be modified by methods
+ # We should change all these to _attr
+
+ self._htmlcontent = '' #: written by buildhtml
+ self.htmlheader = ''
+ #: Place holder for the graph (the HTML div)
+ #: Written by ``buildcontainer``
+ self.container = u''
+ #: Header for javascript code
+ self.containerheader = u''
+ # Loading message
+ self.loading = 'Loading....'
+
+ # Bind Base Classes to self
+ self.options = {
+ "chart": ChartOptions(),
+ #"colorAxis" : ColorAxisOptions(),
+ "colors": ColorsOptions(),
+ "credits": CreditsOptions(),
+ #"data": #NotImplemented
+ "drilldown": DrilldownOptions(),
+ "exporting": ExportingOptions(),
+ "labels": LabelsOptions(),
+ "legend": LegendOptions(),
+ "loading": LoadingOptions(),
+ "navigation": NavigationOptions(),
+ "pane": PaneOptions(),
+ "plotOptions": PlotOptions(),
+ "series": SeriesData(),
+ "subtitle": SubtitleOptions(),
+ "title": TitleOptions(),
+ "tooltip": TooltipOptions(),
+ "xAxis": xAxisOptions(),
+ "yAxis": yAxisOptions(),
+ }
+
+ self.setOptions = {
+ "global": GlobalOptions(),
+ "lang": LangOptions(),
+ }
+
+ self.__load_defaults__()
+
+ # Process kwargs
+ allowed_kwargs = [
+ "width",
+ "height",
+ "renderTo",
+ "backgroundColor",
+ "events",
+ "marginBottom",
+ "marginTop",
+ "marginRight",
+ "marginLeft"
+ ]
+
+ for keyword in allowed_kwargs:
+ if keyword in kwargs:
+ self.options['chart'].update_dict(**{keyword:kwargs[keyword]})
+ # Some Extra Vals to store:
+ self.data_set_count = 0
+ self.drilldown_data_set_count = 0
+
+
+ def __load_defaults__(self):
+ self.options["chart"].update_dict(renderTo='container')
+ self.options["title"].update_dict(text='A New Highchart')
+ self.options["credits"].update_dict(enabled=False)
+
+
+ def add_JSsource(self, new_src):
+ """add additional js script source(s)"""
+ if isinstance(new_src, list):
+ for h in new_src:
+ self.JSsource.append(h)
+ elif isinstance(new_src, basestring):
+ self.JSsource.append(new_src)
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src))
+
+
+ def add_CSSsource(self, new_src):
+ """add additional css source(s)"""
+ if isinstance(new_src, list):
+ for h in new_src:
+ self.CSSsource.append(h)
+ elif isinstance(new_src, basestring):
+ self.CSSsource.append(new_src)
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src))
+
+
+ def add_3d_rotation(self):
+ self.options3d_rotation_flag = True
+
+ def add_data_set(self, data, series_type="line", name=None, **kwargs):
+ """set data for series option in highcharts"""
+
+ self.data_set_count += 1
+ if not name:
+ name = "Series %d" % self.data_set_count
+ kwargs.update({'name':name})
+
+ if series_type == 'treemap':
+ self.add_JSsource('http://code.highcharts.com/modules/treemap.js')
+
+ series_data = Series(data, series_type=series_type, **kwargs)
+
+ series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__())
+ self.data_temp.append(series_data)
+
+
+ def add_drilldown_data_set(self, data, series_type, id, **kwargs):
+ """set data for drilldown option in highcharts"""
+
+ self.drilldown_data_set_count += 1
+ if self.drilldown_flag == False:
+ self.drilldown_flag = True
+
+ kwargs.update({'id':id})
+ series_data = Series(data, series_type=series_type, **kwargs)
+
+ series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__())
+ self.drilldown_data_temp.append(series_data)
+
+
+ def add_data_from_jsonp(self, data_src, data_name='json_data', series_type="line", name=None, **kwargs):
+ """set map data directly from a https source
+ the data_src is the https link for data
+ and it must be in jsonp format
+ """
+ if not self.jsonp_data_flag:
+ self.jsonp_data_flag = True
+
+ if data_name == 'data':
+ data_name = 'json_'+ data_name
+
+ self.jsonp_data = data_name
+ self.add_data_set(RawJavaScriptText(data_name), series_type, name=name, **kwargs)
+ # DEM 2017/07/27: Append new JSON data source to a list instead of
+ # replacing whatever already exists
+ self.jsonp_data_url_list.append(json.dumps(data_src))
+
+
+ def add_JSscript(self, js_script, js_loc):
+ """add (highcharts) javascript in the beginning or at the end of script
+ use only if necessary
+ """
+ if js_loc == 'head':
+ self.jscript_head_flag = True
+ if self.jscript_head:
+ self.jscript_head = self.jscript_head + '\n' + js_script
+ else:
+ self.jscript_head = js_script
+ elif js_loc == 'end':
+ self.jscript_end_flag = True
+ if self.jscript_end:
+ self.jscript_end = self.jscript_end + '\n' + js_script
+ else:
+ self.jscript_end = js_script
+ else:
+ raise OptionTypeError("Not An Accepted script location: %s, either 'head' or 'end'"
+ % js_loc)
+
+
+ def set_options(self, option_type, option_dict, force_options=False):
+ """set plot options """
+ if force_options:
+ self.options[option_type].update(option_dict)
+ elif (option_type == 'yAxis' or option_type == 'xAxis') and isinstance(option_dict, list):
+ # For multi-Axis
+ self.options[option_type] = MultiAxis(option_type)
+ for each_dict in option_dict:
+ self.options[option_type].update(**each_dict)
+ elif option_type == 'colors':
+ self.options["colors"].set_colors(option_dict) # option_dict should be a list
+ elif option_type == 'zAxis':
+ self.options.update({'zAxis': zAxisOptions()})
+ self.options[option_type].update_dict(**option_dict)
+ elif option_type in ["global" , "lang"]: #Highcharts.setOptions:
+ self.setOptions[option_type].update_dict(**option_dict)
+ elif option_type == 'colorAxis':
+ self.options.update({'colorAxis': ColorAxisOptions()})
+ self.options[option_type].update_dict(**option_dict)
+ else:
+ self.options[option_type].update_dict(**option_dict)
+
+ if option_type == 'chart' and 'options3d' in option_dict:
+ # Add 3d.js into Javascript source header
+ self.add_JSsource("http://code.highcharts.com/highcharts-3d.js")
+
+
+ def set_dict_options(self, options):
+ """for dictionary-like inputs (as object in Javascript)
+ options must be in python dictionary format
+ """
+ if isinstance(options, dict):
+ for key, option_data in options.items():
+ self.set_options(key, option_data)
+ else:
+ raise OptionTypeError("Not An Accepted Input Format: %s. Must be Dictionary" %type(options))
+
+
+ def buildcontent(self):
+ """build HTML content only, no header or body tags"""
+
+ self.buildcontainer()
+ self.option = json.dumps(self.options, cls = HighchartsEncoder)
+ self.setoption = json.dumps(self.setOptions, cls = HighchartsEncoder)
+ self.data = json.dumps(self.data_temp, cls = HighchartsEncoder)
+
+ # DEM 2017/04/25: Make 'data' available as an array
+ # ... this permits jinja2 array access to each data definition
+ # ... which is useful for looping over multiple data sources
+ self.data_list = [json.dumps(x, cls = HighchartsEncoder) for x in self.data_temp]
+
+ if self.drilldown_flag:
+ self.drilldown_data = json.dumps(self.drilldown_data_temp, cls = HighchartsEncoder)
+ self._htmlcontent = self.template_content_highcharts.render(chart=self).encode('utf-8')
+
+
+ def buildhtml(self):
+ """build the HTML page
+ create the htmlheader with css / js
+ create html page
+ """
+ self.buildcontent()
+ self.buildhtmlheader()
+ self.content = self._htmlcontent.decode('utf-8') # need to ensure unicode
+ self._htmlcontent = self.template_page_highcharts.render(chart=self)
+ return self._htmlcontent
+
+
+ def buildhtmlheader(self):
+ """generate HTML header content"""
+
+ if self.drilldown_flag:
+ self.add_JSsource('http://code.highcharts.com/modules/drilldown.js')
+
+
+
+ if self.offline:
+ opener = urllib.request.build_opener()
+ opener.addheaders = [('User-Agent', 'Mozilla/5.0')]
+
+ self.header_css = [
+ '' % opener.open(h).read() for h in self.CSSsource
+ ]
+
+ self.header_js = [
+ '' % opener.open(h).read() for h in self.JSsource
+ ]
+ else:
+ self.header_css = [
+ '' % h for h in self.CSSsource
+ ]
+
+ self.header_js = [
+ '' % h for h in self.JSsource
+ ]
+
+ self.htmlheader = ''
+ for css in self.header_css:
+ self.htmlheader += css
+ for js in self.header_js:
+ self.htmlheader += js
+
+
+ def buildcontainer(self):
+ """generate HTML div"""
+ if self.container:
+ return
+ # Create HTML div with style
+ if self.options['chart'].width:
+ if str(self.options['chart'].width)[-1] != '%':
+ self.div_style += 'width:%spx;' % self.options['chart'].width
+ else:
+ self.div_style += 'width:%s;' % self.options['chart'].width
+ if self.options['chart'].height:
+ if str(self.options['chart'].height)[-1] != '%':
+ self.div_style += 'height:%spx;' % self.options['chart'].height
+ else:
+ self.div_style += 'height:%s;' % self.options['chart'].height
+
+ self.div_name = self.options['chart'].__dict__['renderTo'] # recheck div name
+ self.container = self.containerheader + \
+ '
%s
\n' % (self.div_name, self.div_style, self.loading)
+
+ @property
+ def htmlcontent(self):
+ return self.buildhtml()
+
+ @property
+ def iframe(self):
+ htmlsrcdoc = html.escape(self.htmlcontent)
+ htmlsrcdoc = re.sub('\\n', ' ', htmlsrcdoc)
+ htmlsrcdoc = re.sub(' +', ' ', htmlsrcdoc)
+ width = int(self.options['chart'].__dict__['width']) if self.options['chart'].__dict__.get('width') else 820
+ height = int(self.options['chart'].__dict__['height']) if self.options['chart'].__dict__.get('height') else 520
+
+ if self.options['chart'].__dict__.get('options3d'):
+ if len(htmlsrcdoc) < 99965000 :
+ return ''
+ else:
+ return ''
+ else:
+ return ''
+
+
+ def __str__(self):
+ """return htmlcontent"""
+ #self.buildhtml()
+ return self.htmlcontent
+
+ def save_file(self, filename = 'Chart'):
+ """ save htmlcontent as .html file """
+ filename = filename + '.html'
+
+ with open(filename, 'w') as f:
+ #self.buildhtml()
+ f.write(self.htmlcontent)
+
+ f.closed
+
+class HighchartsEncoder(json.JSONEncoder):
+ def __init__(self, *args, **kwargs):
+ json.JSONEncoder.__init__(self, *args, **kwargs)
+ self._replacement_map = {}
+
+ def default(self, obj):
+ if isinstance(obj, RawJavaScriptText):
+ key = uuid.uuid4().hex
+ self._replacement_map[key] = obj.get_jstext()
+ return key
+ elif isinstance(obj, datetime.datetime):
+ utc = obj.utctimetuple()
+ obj = (u"Date.UTC({year},{month},{day},{hours},{minutes},{seconds},{millisec})"
+ .format(year=utc[0], month=utc[1]-1, day=utc[2], hours=utc[3],
+ minutes=utc[4], seconds=utc[5], millisec=obj.microsecond/1000))
+ return RawJavaScriptText(obj)
+ elif isinstance(obj, BaseOptions) or isinstance(obj, MultiAxis):
+ return obj.__jsonable__()
+ elif isinstance(obj, CSSObject) or isinstance(obj, Formatter) or isinstance(obj, JSfunction):
+ return obj.__jsonable__()
+ elif isinstance(obj, SeriesOptions) or isinstance(obj, Series):
+ return obj.__jsonable__()
+ elif isinstance(obj, CommonObject) or isinstance(obj, ArrayObject) or isinstance(obj, ColorObject):
+ return obj.__jsonable__()
+ else:
+ return json.JSONEncoder.default(self, obj)
+
+ def encode(self, obj):
+ result = json.JSONEncoder.encode(self, obj)
+ for k, v in self._replacement_map.items():
+ result = result.replace('"{}"'.format(k), v)
+ return result
+
+
+class OptionTypeError(Exception):
+
+ def __init__(self,*args):
+ self.args = args
diff --git a/build/lib/highcharts/highcharts/options.py b/build/lib/highcharts/highcharts/options.py
new file mode 100644
index 0000000..d91b827
--- /dev/null
+++ b/build/lib/highcharts/highcharts/options.py
@@ -0,0 +1,657 @@
+# -*- coding: UTF-8 -*-
+from past.builtins import basestring
+
+from .highchart_types import OptionTypeError, Series, SeriesOptions
+from .common import Formatter, Events, Position, ContextButton, Options3d, ResetZoomButton, \
+ DrillUpButton, Labels, PlotBands, PlotLines, Title, Items, Navigation, Background, Breaks, \
+ DataClasses, DateTimeLabelFormats, Zones, Levels, Marker, \
+ JSfunction, ColorObject, CSSObject, SVGObject, CommonObject, ArrayObject
+
+import json, datetime
+
+# Base Option Class
+class BaseOptions(object):
+
+ def __init__(self,**kwargs):
+ self.update_dict(**kwargs)
+
+ def __display_options__(self):
+ print(json.dumps(self.__dict__, indent=4, sort_keys=True))
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def __validate_options__(self, k, v, ov):
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,dict) and isinstance(ov,dict):
+ keys = v.keys()
+ if len(keys) > 1:
+ raise NotImplementedError
+ return isinstance(v[keys[0]],ov[keys[0]])
+ return isinstance(v, ov)
+
+ def update_dict(self, **kwargs):
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ # if isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), SeriesOptions):
+ if k in PlotOptions.ALLOWED_OPTIONS.keys():
+ if self.__getattr__(k):
+ self.__dict__[k].update(series_type=k, **v)
+ else:
+ v = SeriesOptions(series_type=k, **v)
+ self.__dict__.update({k:v})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), CommonObject):
+ if isinstance(v, dict):
+ if self.__getattr__(k):
+ self.__dict__[k].update(v) #update dict
+ else: # first
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be dictionary" % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), ArrayObject):
+ if self.__getattr__(k): #existing attr
+ if isinstance(v, dict):
+ self.__dict__[k].update(v) # update array
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].update(item) # update array
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be list or dictionary"
+ % type(v))
+ else: #first
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, list):
+ if len(v) == 1:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v[0])})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v[0])})
+ for item in v[1:]:
+ self.__dict__[k].update(item)
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be list or dictionary"
+ % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ (isinstance(self.ALLOWED_OPTIONS[k][0](), CSSObject) or isinstance(self.ALLOWED_OPTIONS[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items(): # check if v has object input
+ self.__dict__[k].__options__().update({key:value})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and (isinstance(self.ALLOWED_OPTIONS[k][0](), JSfunction) or \
+ isinstance(self.ALLOWED_OPTIONS[k][0](), Formatter) or isinstance(self.ALLOWED_OPTIONS[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+
+ else:
+ print(self.ALLOWED_OPTIONS)
+ print(k, v)
+ raise OptionTypeError("Not An Accepted Option Type: %s" % k)
+
+
+ def __getattr__(self, item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class ChartOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "alignTicks": bool,
+ "animation": [bool, dict, basestring],
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": int,
+ "className": basestring,
+ "defaultSeriesType": basestring,
+ "events": (Events, dict),
+ "height": [int,basestring],
+ "ignoreHiddenSeries": bool,
+ "inverted": bool,
+ "margin": list,
+ "marginBottom": int,
+ "marginLeft": int,
+ "marginRight": int,
+ "marginTop": int,
+ "options3d": (Options3d, dict),
+ "plotBackgroundColor": (ColorObject, basestring, dict),
+ "plotBackgroundImage": basestring,
+ "plotBorderColor": (ColorObject, basestring, dict),
+ "plotBorderWidth": int,
+ "plotShadow": bool,
+ "polar": bool,
+ "reflow": bool,
+ "renderTo": basestring,
+ "resetZoomButton": (ResetZoomButton, dict),
+ "selectionMarkerFill": basestring,
+ "shadow": bool,
+ "showAxes": bool,
+ "spacingBottom": int,
+ "spacingLeft": int,
+ "spacingRight": int,
+ "spacingTop": int,
+ "style": (CSSObject, dict),
+ "type": basestring,
+ "width": [int,basestring],
+ "zoomType": basestring,
+ }
+
+
+class ColorAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "dataClassColor": basestring,
+ "dataClasses": (DataClasses, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineWidth": [float, int],
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": [float, int],
+ "marker": (Marker, dict),
+ "max": [float, int],
+ "maxColor": (ColorObject, basestring, dict),
+ "maxPadding": [float, int],
+ "min": [float, int],
+ "minColor": (ColorObject, basestring, dict),
+ "minPadding": [float, int],
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "reversed": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "stops": list,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": JSfunction,
+ "tickPositions": list,
+ "tickWidth": int,
+ "type": basestring,
+}
+
+
+class ColorsOptions(BaseOptions):
+ """ Special Case, this is simply just an array of colours """
+ def __init__(self):
+ self.colors = {}
+
+ def set_colors(self, colors):
+ if isinstance(colors, basestring):
+ self.colors = ColorObject(colors)
+ elif isinstance(colors, list) or isinstance(colors, dict):
+ self.colors = colors
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(colors))
+
+
+ def __jsonable__(self):
+ return self.colors
+
+
+class CreditsOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "href": basestring,
+ "position": (Position, dict),
+ "style": (CSSObject, dict),
+ "text": basestring,
+ }
+
+
+class DrilldownOptions(BaseOptions): #not implement yet, need work in jinjia
+ ALLOWED_OPTIONS = {
+ "activeAxisLabelStyle": (CSSObject, dict),
+ "activeDataLabelStyle": (CSSObject, dict),
+ "animation": NotImplemented, #(bool, dict), #not sure how to implement
+ "drillUpButton": (DrillUpButton, dict),
+ "series": (SeriesOptions, dict),
+ }
+
+
+class ExportingOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "buttons": (ContextButton, dict),
+ "chartOptions": (ChartOptions, dict),
+ "enabled": bool,
+ "filename": basestring,
+ "formAttributes": NotImplemented,
+ "scale": int,
+ "sourceHeight": int,
+ "sourceWidth": int,
+ "type": basestring,
+ "url": basestring,
+ "width": int,
+ }
+
+
+class GlobalOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "Date": NotImplemented,
+ "VMLRadialGradientURL": basestring,
+ "canvasToolsURL": basestring,
+ "getTimezoneOffset": (JSfunction, basestring),
+ "timezoneOffset": int,
+ "useUTC": bool,
+ }
+
+
+class LabelsOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "items": (Items, dict),
+ "style": (CSSObject, dict),
+ }
+
+
+class LangOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "decimalPoint": basestring,
+ "downloadJPEG": basestring,
+ "downloadPDF": basestring,
+ "downloadPNG": basestring,
+ "donwloadSVG": basestring,
+ "exportButtonTitle": basestring,
+ "loading": basestring,
+ "months": list,
+ "noData": basestring,
+ "numericSymbols": list,
+ "printButtonTitle": basestring,
+ "resetZoom": basestring,
+ "resetZoomTitle": basestring,
+ "shortMonths": list,
+ "thousandsSep": basestring,
+ "weekdays": list,
+ }
+
+
+class LegendOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": int,
+ "enabled": bool,
+ "floating": bool,
+ "itemDistance": int,
+ "itemHiddenStyle": (CSSObject, dict),
+ "itemHoverStyle": (CSSObject, dict),
+ "itemMarginBottom": int,
+ "itemMarginTop": int,
+ "itemStyle": (CSSObject, dict),
+ "itemWidth": int,
+ "labelFormat": basestring,
+ "labelFormatter": (Formatter, JSfunction),
+ "layout": basestring,
+ "lineHeight": int,
+ "margin": int,
+ "maxHeight": int,
+ "navigation": (Navigation, dict),
+ "padding": int,
+ "reversed": bool,
+ "rtl": bool,
+ "shadow": bool,
+ "style": (CSSObject, dict),
+ "symbolHeight": int,
+ "symbolPadding": int,
+ "symbolRadius": int,
+ "symbolWidth": int,
+ "title": (Title, dict),
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "width": int,
+ "x": int,
+ "y": int,
+ }
+
+
+class LoadingOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "hideDuration": int,
+ "labelStyle": (CSSObject, dict),
+ "showDuration": int,
+ "style": (CSSObject, dict),
+ }
+
+
+class NavigationOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "buttonOptions": (ContextButton, dict),
+ "menuItemHoverStyle": (CSSObject, dict),
+ "menuItemStyle": (CSSObject, dict),
+ "menuStyle": (CSSObject, dict),
+ }
+
+
+class PaneOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "background": (Background, list), #arrayObject
+ "center": list,
+ "endAngle": int,
+ "size": int,
+ "startAngle": int,
+ }
+
+
+class PlotOptions(BaseOptions):
+ """ Another Special Case: Interface With all the different Highchart Plot Types Here """
+ ALLOWED_OPTIONS = {
+ "area": (SeriesOptions, dict),
+ "arearange": (SeriesOptions, dict),
+ "areaspline": (SeriesOptions, dict),
+ "areasplinerange": (SeriesOptions, dict),
+ "bar": (SeriesOptions, dict),
+ "boxplot": (SeriesOptions, dict),
+ "bubble": (SeriesOptions, dict),
+ "column": (SeriesOptions, dict),
+ "columnrange": (SeriesOptions, dict),
+ "errorbar": (SeriesOptions, dict),
+ "gauge": (SeriesOptions, dict),
+ "heatmap": (SeriesOptions, dict),
+ "line": (SeriesOptions, dict),
+ "pie": (SeriesOptions, dict),
+ "scatter": (SeriesOptions, dict),
+ "series": (SeriesOptions, dict),
+ "spline": (SeriesOptions, dict),
+ "treemap": (SeriesOptions, dict),
+ }
+
+
+class SeriesData(BaseOptions):
+ """ Another Special Case: Stores Data Series in an array for returning to the chart object """
+ def __init__(self):
+ #self.__dict__.update([])
+ self = []
+
+
+class SubtitleOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "floating": bool,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+
+class TitleOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "floating": bool,
+ "margin": int,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+
+class TooltipOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "animation": bool,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": int,
+ "crosshairs": [bool, list, dict],
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "enabled": bool,
+ "followPointer": bool,
+ "followTouchMove": bool,
+ "footerFormat": basestring,
+ "formatter": (Formatter, JSfunction),
+ "headerFormat": basestring,
+ "pointFormat": basestring,
+ "pointFormatter": (Formatter, JSfunction),
+ "positioner": (JSfunction, basestring),
+ "shadow": bool,
+ "shared": bool,
+ "snap": int,
+ "style": (CSSObject, dict),
+ "useHTML": bool,
+ "valueDecimals": int,
+ "valuePrefix": basestring,
+ "valueSuffix": basestring,
+ "xDateFormat": basestring,
+ }
+
+
+class xAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "allowDecimals": bool,
+ "alternateGridColor": (ColorObject, basestring, dict),
+ "categories": list,
+ 'crosshair': bool,
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineWidth": int,
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": int,
+ "max": [float, int],
+ "maxPadding": [float, int],
+ "maxZoom": NotImplemented,
+ "min": [float, int],
+ "minPadding": [float, int],
+ "minRange": int,
+ "minTickInterval": int,
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "offset": bool,
+ "opposite": bool,
+ "plotBands": (PlotBands, list),
+ "plotLines": (PlotLines, list),
+ "reversed": bool,
+ "showEmpty": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": JSfunction,
+ "tickPositions": list,
+ "tickWidth": int,
+ "tickmarkPlacement": basestring,
+ "title": (Title, dict),
+ "type": basestring,
+ "units": list
+ }
+
+
+class yAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "allowDecimals": bool,
+ "alternateGridColor": (ColorObject, basestring, dict),
+ "breaks": (Breaks, dict),
+ "categories": list,
+ "ceiling": (int, float),
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "floor": (int, float),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineInterpolation": basestring,
+ "gridLineWidth": int,
+ "gridZIndex": int,
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": int,
+ "max": [float, int],
+ "maxColor": (ColorObject, basestring, dict),
+ "maxPadding": [float, int],
+ "maxZoom": NotImplemented,
+ "min": [float, int],
+ "minColor": (ColorObject, basestring, dict),
+ "minPadding": [float, int],
+ "minRange": int,
+ "minTickInterval": int,
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "offset": bool,
+ "opposite": bool,
+ "plotBands": (PlotBands, list),
+ "plotLines": (PlotLines, list),
+ "reversed": bool,
+ "reversedStacks": bool,
+ "showEmpty": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "stackLabels": (Labels, dict),
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "stops": list,
+ "tickAmount": int,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": (JSfunction, basestring),
+ "tickPositions": list,
+ "tickWidth": int,
+ "tickmarkPlacement": basestring,
+ "title": (Title, dict),
+ "type": basestring,
+ "units": list
+ }
+
+class zAxisOptions(BaseOptions): #only for 3D plots
+ ALLOWED_OPTIONS = {
+ "allowDecimals": bool,
+ "alternateGridColor": (ColorObject, basestring, dict),
+ "breaks": (Breaks, dict),
+ "categories": list,
+ "ceiling": (int, float),
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "floor": (int, float),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineInterpolation": basestring,
+ "gridLineWidth": int,
+ "gridZIndex": int,
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": int,
+ "max": [float, int],
+ "maxColor": (ColorObject, basestring, dict),
+ "maxPadding": [float, int],
+ "maxZoom": NotImplemented,
+ "min": [float, int],
+ "minColor": (ColorObject, basestring, dict),
+ "minPadding": [float, int],
+ "minRange": int,
+ "minTickInterval": int,
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "offset": bool,
+ "opposite": bool,
+ "plotBands": (PlotBands, list),
+ "plotLines": (PlotLines, list),
+ "reversed": bool,
+ "reversedStacks": bool,
+ "showEmpty": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "stackLabels": (Labels, dict),
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "stops": list,
+ "tickAmount": int,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": (JSfunction, basestring),
+ "tickPositions": list,
+ "tickWidth": int,
+ "tickmarkPlacement": basestring,
+ "title": (Title, dict),
+ "type": basestring,
+ "units": list
+ }
+
+
+class MultiAxis(object):
+
+ def __init__(self, axis):
+ AXIS_LIST = {
+ "xAxis": xAxisOptions,
+ "yAxis": yAxisOptions
+ }
+ self.axis = []
+ self.AxisObj = AXIS_LIST[axis]
+
+ def update(self, **kwargs):
+ self.axis.append(self.AxisObj(**kwargs))
+
+ def __jsonable__(self):
+ return self.axis
+
diff --git a/build/lib/highcharts/highcharts/templates/base.html b/build/lib/highcharts/highcharts/templates/base.html
new file mode 100644
index 0000000..401d656
--- /dev/null
+++ b/build/lib/highcharts/highcharts/templates/base.html
@@ -0,0 +1,21 @@
+{% block container %}
+{% endblock %}
+
+{% block start_script %}
+
+{% endblock endscript %}
\ No newline at end of file
diff --git a/build/lib/highcharts/highcharts/templates/content.html b/build/lib/highcharts/highcharts/templates/content.html
new file mode 100644
index 0000000..b92181e
--- /dev/null
+++ b/build/lib/highcharts/highcharts/templates/content.html
@@ -0,0 +1,88 @@
+{% extends "base.html" %}
+{% block container %}
+ {{ chart.container }}
+{% endblock container %}
+
+{% block body_head %}
+
+ {% if chart.jscript_head_flag %}
+ {{chart.jscript_head}}
+ {% endif %}
+
+{% endblock body_head %}
+
+{% block body_content %}
+
+ Highcharts.setOptions({{chart.setoption}});
+ var option = {{chart.option}};
+
+ {% if chart.mapdata_flag %}
+ var geojson = {{chart.mapdata}}
+ {% endif %}
+
+ {% if chart.drilldown_flag %}
+ var drilldowndata = {{chart.drilldown_data}};
+ option.drilldown.series = drilldowndata;
+ {% endif %}
+
+ var chart = new Highcharts.Chart(option);
+
+ {# DEM 2017/07/27: Use a list of JSONP data sources
+ {# DEM 2017/07/27: This implementation is limited and could easily be improved! #}
+ {% if chart.jsonp_data_flag %}
+ {% for data_url in chart.jsonp_data_url_list %}
+
+ $.getJSON({{data_url}}, function ({{chart.jsonp_data}})
+ {
+ chart.addSeries({{chart.data_list[loop.index0]}});
+ });
+
+ {% endfor %}
+ {% else %}
+ var data = {{chart.data}};
+ var dataLen = data.length;
+ for (var ix = 0; ix < dataLen; ix++) {
+ chart.addSeries(data[ix]);
+ }
+ {% endif %}
+
+
+ {% if chart.jscript_end_flag %}
+ {{chart.jscript_end}}
+ {% endif %}
+
+ {% if chart.options3d_rotation_flag %}
+ $(chart.container).bind('mousedown.hc touchstart.hc', function (e) {
+ e = chart.pointer.normalize(e);
+
+ var posX = e.pageX,
+ posY = e.pageY,
+ alpha = chart.options.chart.options3d.alpha,
+ beta = chart.options.chart.options3d.beta,
+ newAlpha,
+ newBeta,
+ sensitivity = 5;
+
+ $(document).bind({
+ 'mousemove.hc touchdrag.hc': function (e) {
+
+ newBeta = beta + (posX - e.pageX) / sensitivity;
+ chart.options.chart.options3d.beta = newBeta;
+
+ newAlpha = alpha + (e.pageY - posY) / sensitivity;
+ chart.options.chart.options3d.alpha = newAlpha;
+
+ chart.redraw(false);
+ },
+ 'mouseup touchend': function () {
+ $(document).unbind('.hc');
+ }
+ });
+ });
+ {% endif %}
+
+{% endblock body_content %}
+
+{% block body_end %}
+
+{% endblock body_end %}
diff --git a/build/lib/highcharts/highcharts/templates/page.html b/build/lib/highcharts/highcharts/templates/page.html
new file mode 100644
index 0000000..3559aaa
--- /dev/null
+++ b/build/lib/highcharts/highcharts/templates/page.html
@@ -0,0 +1,12 @@
+
+
+
+
+ {% for header_element in chart.header_css+chart.header_js %}
+ {{ header_element }}
+ {% endfor %}
+
+
+ {{ chart.content }}
+
+
diff --git a/build/lib/highcharts/highcharts/templates/test.html b/build/lib/highcharts/highcharts/templates/test.html
new file mode 100644
index 0000000..63eecc5
--- /dev/null
+++ b/build/lib/highcharts/highcharts/templates/test.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ {{ chart.title }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/lib/highcharts/highmaps/__init__.py b/build/lib/highcharts/highmaps/__init__.py
new file mode 100644
index 0000000..a15132e
--- /dev/null
+++ b/build/lib/highcharts/highmaps/__init__.py
@@ -0,0 +1 @@
+from .highmaps import Highmap
\ No newline at end of file
diff --git a/build/lib/highcharts/highmaps/common.py b/build/lib/highcharts/highmaps/common.py
new file mode 100644
index 0000000..b03309d
--- /dev/null
+++ b/build/lib/highcharts/highmaps/common.py
@@ -0,0 +1,701 @@
+# -*- coding: UTF-8 -*-
+""" Python-Highmaps common.py
+Common Functions For Highmaps
+"""
+from past.builtins import basestring
+import datetime, re
+
+FORMATTER_TYPE_MAPPINGS = {
+ "default": "function() { return this.value }",
+ "date": "function() { return''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + ': '+ this.y; }",
+ "pie": "function() { return ''+ this.point.name +': '+ \
+ this.percentage +' %'; }",
+ "pound_yAxis": "function() { '£' + return this.value }",
+ "pound_tooltip": "function() { return''+ this.x + ': '+ '£' +this.y; }",
+ "percent": "function() { return this.value + ' %' }",
+ "default_tooltip": "function () { return''+ this.series.name + ': ' + this.y; }",
+ "percent_tooltip": "function () { return''+ this.series.name + ': ' + this.y + ' %'; }",
+ "date_percent_tooltip": "function () { return''+Highcharts.dateFormat('%e. %b %Y',this.x) + '
'+ this.series.name + ': ' + this.y + ' %'; }",
+ 'filesize': """
+function() {
+ fileSizeInBytes = this.value;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'date_filesize_tooltip': """
+function() {
+ fileSizeInBytes = this.y;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return ''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + '
' + this.series.name + ': ' + Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'filesize_tooltip': """
+function() {
+ fileSizeInBytes = this.y;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return '' + this.series.name + ': ' + Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'duration': """
+function() {
+ seconds = this.value;
+
+ days = Math.floor(seconds / 86400);
+ seconds = seconds - (days * 86400);
+
+ hours = Math.floor(seconds / 3600);
+ seconds = seconds - (hours * 3600);
+
+ mins = Math.floor(seconds / 60);
+ seconds = seconds - (mins * 60);
+
+ res = "";
+ if(days > 0){
+ res += days + " d ";
+ }
+ if(hours > 0){
+ res += hours + ' hr ';
+ }
+ if(mins > 0){
+ res += mins + ' m ';
+ }
+ if(seconds > 0){
+ res += seconds + ' s ';
+ }
+ return res;
+}
+""",
+ 'date_duration_tooltip': """
+function() {
+ seconds = this.y;
+
+ days = Math.floor(seconds / 86400);
+ seconds = seconds - (days * 86400);
+
+ hours = Math.floor(seconds / 3600);
+ seconds = seconds - (hours * 3600);
+
+ mins = Math.floor(seconds / 60);
+ seconds = seconds - (mins * 60);
+
+ res = "";
+ if(days > 0){
+ res += days + " d ";
+ }
+ if(hours > 0){
+ res += hours + ' hr ';
+ }
+ if(mins > 0){
+ res += mins + ' m ';
+ }
+ if(seconds > 0){
+ res += seconds + ' s ';
+ }
+ return ''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + '
'+ this.series.name + ': ' + res;
+}
+""",
+}
+
+REGEX_LIST = {
+ "re_funct" : re.compile(r'.*function\(.*\)\{.*\}', re.I), #for inputs such as function(xxx){xxx}
+ "re_hcharts" : re.compile(r'.*Highcharts.*', re.I), #for inputs such as highcharts.xxxxx
+}
+
+
+class Formatter(object):
+ """ Base Formatter Class """
+
+ def __init__(self, format=None):
+ ### Choose either from default functions in FORMATTER_TYPE_MAPPINGS using format_type
+ ### or wriet a function in format_string
+ if format:
+ if format in FORMATTER_TYPE_MAPPINGS:
+ self.formatter = RawJavaScriptText(FORMATTER_TYPE_MAPPINGS[format])
+ elif isinstance(format, basestring):
+ self.formatter = RawJavaScriptText(format)
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % basestring)
+
+ def __options__(self):
+ return self.formatter
+
+ def __jsonable__(self):
+ return self.formatter
+
+class MapObject(object):
+ """ Base Map Class """
+
+ def __init__(self, mapdata=None):
+ if mapdata:
+ if isinstance(mapdata, basestring):
+ self.map = RawJavaScriptText(mapdata)
+ elif isinstance(mapdata, JSfunction):
+ self.map = mapdata
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % basestring)
+
+ def __options__(self):
+ return self.map
+
+ def __jsonable__(self):
+ return self.map
+
+
+class ColorObject(object):
+ """ color object """
+
+ def __init__(self, color=None, **kwargs):
+ if not color:
+ color = kwargs
+
+ if color:
+ if isinstance(color, dict):
+ tmp = []
+ for i, item in enumerate(color['stops']):
+ tmp.append([RawJavaScriptText(x) if isinstance(x, basestring) and any([REGEX_LIST[key].search(x) for key in REGEX_LIST.keys()])
+ else x for x in item ])
+ color['stops'] = tmp
+ self.color = color
+ elif any([REGEX_LIST[key].search(color) for key in REGEX_LIST.keys()]):
+ self.color = RawJavaScriptText(color)
+ elif isinstance(color, basestring):
+ self.color = color
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % (basestring or dict))
+ else:
+ self.color = None
+
+ def __options__(self):
+ return self.color
+
+ def __jsonable__(self):
+ return self.color
+
+
+class CSSObject(object):
+ """ CSS style class """
+
+ def __init__(self, **kwargs):
+ self.css = kwargs
+
+ for k, v in self.css.items():
+ if isinstance(v, basestring) and any([REGEX_LIST[key].search(v) for key in REGEX_LIST.keys()]):
+ v = RawJavaScriptText(v)
+ self.css.update({k:v})
+
+ def __options__(self):
+ return self.css
+
+ def __jsonable__(self):
+ return self.css
+
+class SVGObject(object):
+ """ SVG style class """
+
+ def __init__(self, **kwargs):
+ self.svg = kwargs
+
+ for k, v in self.svg.items():
+ if isinstance(v, basestring) and any([REGEX_LIST[key].search(v) for key in REGEX_LIST.keys()]):
+ v = RawJavaScriptText(v)
+ self.svg.update({k:v})
+
+ def __options__(self):
+ return self.svg
+
+ def __jsonable__(self):
+ return self.svg
+
+class JSfunction(object):
+
+ def __init__(self, function = None):
+ if function:
+ if isinstance(function, basestring):
+ self.function = RawJavaScriptText(function)
+ elif isinstance(function, JSfunction):
+ self.function = function
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % basestring)
+
+ def __options__(self):
+ return self.function
+
+ def __jsonable__(self):
+ return self.function
+
+
+class RawJavaScriptText:
+
+ def __init__(self, jstext):
+ self._jstext = jstext
+ def get_jstext(self):
+ return self._jstext
+
+
+class CommonObject(object):
+
+ def __init__(self, **kwargs):
+ self.process_kwargs(kwargs)
+
+ def __validate_options__(self, k,v,ov):
+
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def update(self, kwargs):
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), CommonObject):
+ # re-construct input dict with existing options in objects
+ if self.__getattr__(k):
+ if isinstance(v, dict):
+ self.__options__()[k].update(v)
+ else:
+ self.__options__()[k].__options__().update(v)
+ else:
+ self.__options__().update({k:allowed_args[k][0](**v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), ArrayObject):
+ # update array
+ if isinstance(v, dict):
+ self.__dict__[k].append(self.ALLOWED_OPTIONS[k][0](**v))
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].append(self.ALLOWED_OPTIONS[k][0](**item))
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ (isinstance(self.ALLOWED_OPTIONS[k][0](), CSSObject) or isinstance(self.ALLOWED_OPTIONS[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items():
+ self.__dict__[k].__options__().update({key:value})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and (isinstance(self.ALLOWED_OPTIONS[k][0](), JSfunction) or \
+ isinstance(self.ALLOWED_OPTIONS[k][0](), Formatter) or isinstance(self.ALLOWED_OPTIONS[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+
+ else:
+ raise OptionTypeError("Not An Accepted Option Type: %s" % k)
+
+ def process_kwargs(self,kwargs):
+
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if self.__validate_options__(k,v,self.ALLOWED_OPTIONS[k]):
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ self.ALLOWED_OPTIONS[k][0] in IDV_OBJECT_LIST:
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % self.ALLOWED_OPTIONS[k])
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For CommonObject:" % k)
+
+
+class Events(CommonObject):
+ """ Class for event listener """
+
+ ALLOWED_OPTIONS = {
+ "addSeries": (JSfunction, basestring),
+ "afterPrint": (JSfunction, basestring),
+ "beforePrint": (JSfunction, basestring),
+ "click": (JSfunction, basestring),
+ "drilldown": (JSfunction, basestring),
+ "drillup": (JSfunction, basestring),
+ "load": (JSfunction, basestring),
+ "redraw": (JSfunction, basestring),
+ "selection": (JSfunction, basestring),
+ "afterAnimate": (JSfunction, basestring),
+ "checkboxClick": (JSfunction, basestring),
+ "hide": (JSfunction, basestring),
+ "legendItemClick": (JSfunction, basestring),
+ "mouseOut": (JSfunction, basestring),
+ "mouseOver": (JSfunction, basestring),
+ "show": (JSfunction, basestring),
+ "remove": (JSfunction, basestring),
+ "select": (JSfunction, basestring),
+ "unselect": (JSfunction, basestring),
+ "update": (JSfunction, basestring),
+ "afterBreaks": (JSfunction, basestring),
+ "afterSetExtremes": (JSfunction, basestring),
+ "pointBreak": (JSfunction, basestring),
+ "setExtremes": (JSfunction, basestring)
+ }
+
+class Point(CommonObject):
+ ALLOWED_OPTIONS = {
+ "events": Events
+ }
+
+class Position(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+class ContextButton(CommonObject):
+ """ Option class for the export button """
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "alignTo": basestring,
+ "enabled": bool,
+ "height": int,
+ "menuItems": NotImplemented,
+ "onclick": (JSfunction, basestring),
+ "style": (CSSObject, dict),
+ "symbol": basestring,
+ "symbolFill": basestring,
+ "symbolSize": int,
+ "symbolStroke": basestring,
+ "symbolStrokeWidth": int,
+ "symbolX": [float, int],
+ "symbolY": [float, int],
+ "text": basestring,
+ "theme": NotImplemented,#ThemeObject
+ "verticalAlign": basestring,
+ "width": int,
+ "x": int,
+ "y": int,
+ }
+
+class Button(CommonObject):
+ ALLOWED_OPTIONS = {
+ "zoomIn": (ContextButton, dict),
+ "zoomOut": (ContextButton, dict),
+ }
+
+class Options3d(CommonObject):
+ ALLOWED_OPTIONS = {
+ "alpha": [float, int],
+ "beta": [float, int],
+ "depth": int,
+ "enabled": bool,
+ "frame": NotImplemented, # FrameObject
+ "viewDistance": int
+ }
+
+
+class ResetZoomButton(CommonObject):
+ ALLOWED_OPTIONS = {
+ "position": (Position, dict),
+ "relativeTo": basestring,
+ "theme": NotImplemented #ThemeObject
+ }
+
+class DrillUpButton(CommonObject):
+ ALLOWED_OPTIONS = {
+ "position": (Position, dict),
+ "relativeTo": basestring,
+ "theme": NotImplemented #ThemeObject
+ }
+
+class Labels(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": [float, int],
+ "borderWidth": [int, float, basestring],
+ "color": (ColorObject, basestring, dict),
+ "connectorColor": (ColorObject, basestring, dict),
+ "connectorPadding": [float, int],
+ "connectorWidth": [float, int],
+ "crop": bool,
+ "defer": bool,
+ "distance": int,
+ "enabled": bool,
+ "format": [basestring, type(None)],
+ "formatter": (Formatter, JSfunction, basestring),
+ "inside": bool,
+ "overflow": basestring,
+ "padding": [float, int],
+ "rotation": int,
+ "shadow": [bool, dict], #shadow object
+ "shape": basestring,
+ "softConnector": bool,
+ "staggerLines": int,
+ "step": int,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "textAlign": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ "zIndex": int,
+ }
+
+class Title(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "enabled": bool,
+ "margin": int,
+ "offset": int,
+ "rotation": int,
+ "style": (CSSObject, dict),
+ "text": [basestring, type(None)]
+ }
+
+class Navigation(CommonObject):
+ ALLOWED_OPTIONS = {
+ "activeColor": (ColorObject, basestring, dict),
+ "animation": NotImplemented, #need animation object
+ "arrowSize": int,
+ "inactiveColor": (ColorObject, basestring, dict),
+ "style": (CSSObject, dict),
+ }
+
+class DateTimeLabelFormats(CommonObject):
+ ALLOWED_OPTIONS = {
+ "millisecond": basestring,
+ "second": basestring,
+ "minute": basestring,
+ "hour": basestring,
+ "day": basestring,
+ "week": basestring,
+ "month": basestring,
+ "year": basestring,
+ }
+
+class Select(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "radius": int,
+ }
+
+class States(CommonObject):
+ ALLOWED_OPTIONS = {
+ "hover": dict,
+ "select": dict,
+ }
+
+class Marker(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "height": int,
+ "lineWidth": int,
+ "lineColor": (ColorObject, basestring, dict),
+ "radius": int,
+ "states": (States, dict),
+ "symbol": basestring,
+ "width": int
+ }
+
+class Halo(CommonObject):
+ ALLOWED_OPTIONS = {
+ "attributes": (SVGObject, dict),
+ "opacity": float,
+ "size": int
+ }
+
+class Hover(CommonObject):
+ ALLOWED_OPTIONS = {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, float, basestring],
+ "brightness": [int, float],
+ "color": (ColorObject, basestring, dict),
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "halo": (Halo, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "lineWidthPlus": int,
+ "marker": (Marker, dict),
+ "radius": int,
+ "radiusPlus": int,
+ }
+
+class States(CommonObject):
+ ALLOWED_OPTIONS = {
+ "hover": (Hover, dict),
+ "normal": dict, #need animation object
+ "select": (Select, dict)
+ }
+
+class Tooltip(CommonObject):
+ ALLOWED_OPTIONS = {
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "followPointer": bool,
+ "followTouchMove": bool,
+ "footerFormat": basestring,
+ "headerFormat": basestring,
+ "hideDelay": int,
+ "pointFormat": basestring,
+ "pointFormatter": (Formatter, JSfunction, basestring),
+ "shape": basestring,
+ "valueDecimals": int,
+ "valuePrefix": basestring,
+ "valueSuffix": basestring,
+ "xDateFormat": basestring
+ }
+
+
+class ArrayObject(object):
+
+ def __init__(self, **kwargs):
+ self.data = []
+ self.process_kwargs(kwargs)
+
+ def __validate_options__(self, k,v,ov):
+
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.data
+
+ def __jsonable__(self):
+ return self.data
+
+ def update(self, kwargs):
+ self.process_kwargs(kwargs)
+
+ def process_kwargs(self,kwargs):
+ temp = {}
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if self.__validate_options__(k,v,self.ALLOWED_OPTIONS[k]):
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ self.ALLOWED_OPTIONS[k][0] in IDV_OBJECT_LIST:
+ if isinstance(v, dict):
+ temp.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ temp.update({k:v})
+ else:
+ temp.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ temp.update({k:v})
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % self.ALLOWED_OPTIONS[k])
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For ArrayObject:" % k)
+ self.data.append(temp)
+
+class Items(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "html": basestring,
+ "style": (CSSObject, dict)
+ }
+
+class Background(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "backgroundColor": (ColorObject, basestring, dict),
+ "shape": basestring,
+ "innerWidth": int,
+ "outerWidth": int,
+ "borderWidth": [int, float, basestring],
+ "borderColor": (ColorObject, basestring, dict),
+ "outerRadius": basestring,
+ }
+
+class Breaks(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "breakSize": int,
+ "from": [int, float],
+ "repeat": int,
+ "to": [int, float],
+ }
+
+class DataClasses(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "from": [int, float],
+ "name": basestring,
+ "to": [int, float],
+ }
+
+class Levels(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderDashStyle": basestring,
+ "borderWidth": [int, basestring],
+ "color": (ColorObject, basestring, dict),
+ "dataLabels": (Labels, dict),
+ "layoutAlgorithm": basestring,
+ "layoutStartingDirection": basestring,
+ "level": int,
+ }
+
+
+IDV_OBJECT_LIST = [JSfunction, Formatter, Halo, Marker, Labels, Button,
+ Position, Hover, Select, Events, States, ContextButton,
+ CSSObject, SVGObject, ColorObject,
+ RawJavaScriptText, DateTimeLabelFormats]
+
+
+class OptionTypeError(Exception):
+
+ def __init__(self,*args):
+ self.args = args
diff --git a/build/lib/highcharts/highmaps/highmap_helper.py b/build/lib/highcharts/highmaps/highmap_helper.py
new file mode 100644
index 0000000..834662b
--- /dev/null
+++ b/build/lib/highcharts/highmaps/highmap_helper.py
@@ -0,0 +1,255 @@
+# -*- coding: utf-8 -*-
+from future.standard_library import install_aliases
+install_aliases()
+from past.builtins import basestring
+
+from urllib.request import urlopen
+import urllib
+
+import json, os, sys
+import datetime, re
+from datetime import tzinfo
+
+def jsonp_loader(url, prefix_regex=r'^(.*\()', suffix_regex=r'(\);)$', sub_d=None, sub_by=''):
+ """Request (JSON) data from a server in a different domain (JSONP)
+ and covert to python readable data.
+ 1. url is the url (https) where data is located
+ 2. "prefix_regex" and "suffix_regex" are regex patterns used to
+ remove JSONP specific prefix and suffix, such as callback header: "callback(" and end: ");",
+ 3. "sub_d" is regex patterns for any unwanted string in loaded json data (will be replaced by sub_by).
+ 4. "sub_by" is the string to replace any unwanted string defined by sub_d
+ For function coverstion, such as Data.UTC to datetime.datetime, please check JSONPDecoder
+ """
+
+ hdr = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7'}
+ req = urllib.request.Request(url, headers=hdr)
+ page = urlopen(req)
+ result = page.read().decode('utf-8')
+ # replace all the redundant info with sub_by
+ if sub_d:
+ result = re.sub(sub_d, sub_by, result)
+
+ prefix = re.search(prefix_regex, result).group()
+ suffix = re.search(suffix_regex, result).group()
+ if result.startswith(prefix) and result.endswith(suffix):
+ result = result[len(prefix):-len(suffix)]
+ return json.loads(result, encoding='utf8', cls=JSONPDecoder)
+
+def js_map_loader(url):
+ """Load map data from a .js source. It is designed for using highcharts' map collection:
+ https://code.highcharts.com/mapdata/. Map data from other sources are not guaranteed
+ """
+
+ hdr = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7'}
+ req = urllib.request.Request(url, headers=hdr)
+ page = urlopen(req)
+ result = page.read().decode('utf-8')
+ result = result[len(re.search(r'^.* = ', result).group()):]
+
+ return json.loads(result)
+
+def geojson_handler(geojson, hType='map'):
+ """Restructure a GeoJSON object in preparation to be added directly by add_map_data or add_data_set methods.
+ The geojson will be broken down to fit a specific Highcharts (highmaps) type, either map, mapline or mappoint.
+ Meta data in GeoJSON's properties object will be copied directly over to object['properties']
+ 1. geojson is the map data (GeoJSON) to be converted
+ 2. hType is the type of highmap types. "map" will return GeoJSON polygons and multipolygons.
+ "mapline" will return GeoJSON linestrings and multilinestrings.
+ "mappoint" will return GeoJSON points and multipoints.
+ default: "map"
+ """
+
+ hType_dict = {
+ 'map': ['polygon', 'multipolygon'],
+ 'mapline': ['linestring', 'multilinestring'],
+ 'mappoint': ['point', 'multipoint'],
+ }
+
+
+ oldlist = [x for x in geojson['features'] if x['geometry']['type'].lower() in hType_dict[hType]]
+ newlist = []
+ for each_dict in oldlist:
+ geojson_type = each_dict['geometry']['type'].lower()
+
+ if hType == 'mapline':
+ newlist.append(
+ {'name': each_dict['properties'].get('name', None),
+ 'path': _coordinates_to_path(each_dict['geometry']['coordinates'], hType, geojson_type),
+ 'properties': each_dict['properties'],
+ }
+ )
+ elif hType == 'map':
+ newlist.append(
+ {'name': each_dict['properties']['name'],
+ 'path': _coordinates_to_path(each_dict['geometry']['coordinates'], hType, geojson_type),
+ 'properties': each_dict['properties'],
+ }
+ )
+ elif hType == 'mappoint':
+ newlist.append(
+ {'name': each_dict['properties']['name'],
+ 'x': each_dict['geometry']['coordinates'][0],
+ 'y': -each_dict['geometry']['coordinates'][1],
+ 'properties': each_dict['properties'],
+ }
+ )
+
+ return newlist
+
+def interpolateRGB(lowRGB, highRGB, fraction):
+ color = []
+
+ for i in range(3):
+ color.append((highRGB[i] - lowRGB[i]) * fraction + lowRGB[i])
+
+ return 'rgb(' + str(int(round(color[0],0))) + ',' + str(int(round(color[1],0))) + ',' + \
+ str(int(round(color[2],0))) + ')'
+
+def _coordinates_to_path(coordinates_array, hType, geojson_type):
+ new_array = []
+
+ def _svglabel(alist):
+ newlist = []
+ for i, item in enumerate(alist):
+ if i == 0:
+ item = ['M']+[item[0], -item[1]]
+ elif i == 1:
+ item = ['L']+[item[0], -item[1]]
+ else:
+ item = [item[0], -item[1]]
+ newlist += item
+ return newlist
+
+ if geojson_type == 'multipolygon':
+ coordinates_array = [item for sublist in coordinates_array for item in sublist]
+
+ if geojson_type in ['polygon', 'multipolygon', 'multilinestring']:
+ for item in coordinates_array:
+ new_array += _svglabel(item)
+ else:
+ new_array += _svglabel(coordinates_array)
+
+ if hType == 'map':
+ new_array+=['z']
+
+ return new_array
+
+
+def _path_to_array(path):
+ path = path.replace(r'/([A-Za-z])/g', r' $1 ')
+ path = path.replace(r'/^\s*/', "").replace(r'/\s*$/', "")
+ path = path.split(" ");
+ for i, v in enumerate(path):
+ try:
+ path[i] = float(v)
+ except:
+ pass
+ return path
+
+if __name__ == '__main__':
+ print(path_to_array("M 4687 2398 L 4679 2402 4679 2398 Z"))
+
+class JSONPDecoder(json.JSONDecoder):
+ """Customized JSON decoder. It is used to convert everything
+ that is python non-compatible (usually Javascript functions)
+ to one that can be read by python. It needs to coordinate with
+ customized JSON encoder in main library, such as highcharts.py,
+ to convert back to Javascript-compatiable functions.
+ For example: in _iterdecode, it checks if queried JSON has Data.UTC
+ and (if yes)converts it to datetime.datetime
+ """
+
+ def decode(self, json_string):
+ """
+ json_string is basicly string that you give to json.loads method
+ """
+
+ default_obj = super(JSONPDecoder, self).decode(json_string)
+
+ return list(self._iterdecode(default_obj))[0]
+
+ def _iterdecode_list(self, lst):
+ new_lst = []
+ for item in lst:
+ for chunk in self._iterdecode(item):
+ new_lst.append(chunk)
+ yield new_lst
+
+ def _iterdecode_dict(self, dct):
+ new_dct = {}
+ for key, value in dct.items():
+ for chunk in self._iterdecode(value):
+ new_dct[key] = chunk
+ yield new_dct
+
+ def _iterdecode(self, obj):
+ if isinstance(obj, (list, tuple)):
+ for chunk in self._iterdecode_list(obj):
+ yield chunk
+
+ elif isinstance(obj, dict):
+ for chunk in self._iterdecode_dict(obj):
+ yield chunk
+
+ elif isinstance(obj, basestring) and JSONPDecoder.is_js_date_utc(obj):
+ m = JSONPDecoder.is_js_date_utc(obj)
+ yield JSONPDecoder.json2datetime(m)
+
+ else:
+ yield obj
+
+ @staticmethod
+ def is_js_date_utc(json):
+ """Check if the string contains Date.UTC function
+ and return match group(s) if there is
+ """
+
+ JS_date_utc_pattern = r'Date\.UTC\(([0-9]+,[0-9]+,[0-9]+)(,[0-9]+,[0-9]+,[0-9]+)?(,[0-9]+)?\)'
+ re_date = re.compile(JS_date_utc_pattern, re.M)
+
+ if re_date.search(json):
+ return re_date.search(json).group(0)
+ else:
+ return False
+
+ @staticmethod
+ def json2datetime(json):
+ """Convert JSON representation to date or datetime object depending on
+ the argument count. Requires UTC datetime representation.
+ Raises ValueError if the string cannot be parsed.
+ """
+
+ json_m = re.search(r'([0-9]+,[0-9]+,[0-9]+)(,[0-9]+,[0-9]+,[0-9]+)?(,[0-9]+)?', json)
+ args=json_m.group(0).split(',')
+
+ try:
+ args=map(int, args)
+ except ValueError:
+ raise ValueError('Invalid arguments: %s'%json)
+
+ if len(args)==3:
+ return datetime.datetime(args[0], args[1]+1, args[2])
+ elif len(args)==6:
+ return datetime.datetime(args[0], args[1]+1, args[2],
+ args[3], args[4], args[5], tzinfo=UTC())
+ elif len(args)==7:
+ args[6]*=1000
+ return datetime.datetime(args[0], args[1]+1, args[2],
+ args[3], args[4], args[5], args[6], tzinfo=UTC())
+ raise ValueError('Invalid number of arguments: %s'%json)
+
+
+class UTC(tzinfo):
+ """UTC"""
+
+ ZERO=datetime.timedelta(0)
+
+ def utcoffset(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return "UTC"
+
+ def dst(self, dt):
+ return ZERO
+
\ No newline at end of file
diff --git a/build/lib/highcharts/highmaps/highmap_types.py b/build/lib/highcharts/highmaps/highmap_types.py
new file mode 100644
index 0000000..40cbbc9
--- /dev/null
+++ b/build/lib/highcharts/highmaps/highmap_types.py
@@ -0,0 +1,301 @@
+# -*- coding: UTF-8 -*-
+from past.builtins import basestring
+import json, datetime
+from .common import Formatter, Events, Position, ContextButton, Options3d, ResetZoomButton, DrillUpButton, Labels, \
+ Marker, Point, States, Tooltip, Title, JSfunction, MapObject, ColorObject, CSSObject, SVGObject, \
+ CommonObject, ArrayObject
+
+PLOT_OPTION_ALLOWED_ARGS = {
+ "common": {
+ "animation": bool,
+ "color": (ColorObject, basestring, dict),
+ "cursor": basestring,
+ "dataLabels": (Labels, dict),
+ "enableMouseTracking": bool,
+ "events": (Events, dict),
+ "id": basestring,
+ "index": [float, int],
+ "marker": (Marker, dict),
+ "name": basestring,
+ "point": (Point, dict),
+ "selected": bool,
+ "showCheckbox": bool,
+ "showInLegend": bool,
+ "states": (States, dict),
+ "stickyTracking": bool,
+ "tooltip": (Tooltip, dict),
+ "visible": bool,
+ "xAxis": [int, basestring],
+ "yAxis": [int, basestring],
+ "zIndex": int,
+ }, "heatmap": {
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, float, basestring],
+ "colsize": int,
+ "legendIndex": [int, float],
+ "rowsize": int,
+ "mapData": (MapObject, list, basestring),
+ "nullColor": (ColorObject, basestring, dict),
+ "shadow": [bool, dict], #shadow object
+ },
+ "map": {
+ "allAreas": bool,
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, float, basestring],
+ "dashStyle": basestring,
+ "joinBy": [basestring, list],
+ "legendIndex": [int, float],
+ "mapData": (MapObject, list, basestring),
+ "nullColor": (ColorObject, basestring, dict),
+ "shadow": [bool, dict],
+ },
+ "mapbubble": {
+ "allAreas": bool,
+ "allowPointSelect": bool,
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, float, basestring],
+ "displayNegative": bool,
+ "joinBy": [basestring, list],
+ "legendIndex": [int, float],
+ "mapData": (MapObject, list, basestring),
+ "maxSize": [basestring, int],
+ "minSize": [basestring, int],
+ "negativeColor": (ColorObject, basestring, dict),
+ "shadow": [bool, dict],
+ "sizeBy": basestring,
+ "zMax": int,
+ "zMin": int,
+ "zThreshold": [int, float],
+ },
+ "mapline": {
+ "allAreas": bool,
+ "allowPointSelect": bool,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "joinBy": [basestring, list],
+ "legendIndex": [int, float],
+ "lineWidth": [int, float],
+ "mapData": (MapObject, list, basestring),
+ "maxSize": [basestring, int],
+ "minSize": [basestring, int],
+ "negativeColor": (ColorObject, basestring, dict),
+ "shadow": [bool, dict],
+ "sizeBy": basestring,
+ "zMax": int,
+ "zMin": int,
+ "zThreshold": [int, float],
+ },
+ "mappoint": {
+ "legendIndex": [int, float],
+ "mapData": (MapObject, list, basestring),
+ },
+}
+
+DATA_SERIES_ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "dataLabels": (Labels, dict),
+ "dataParser": NotImplemented,
+ "dataURL": NotImplemented,
+ "drilldown": basestring,
+ "events": (Events, dict),
+ "high": [int, float],
+ "id": basestring,
+ "index": int,
+ "legendIndex": int,
+ "lat": [float, int],
+ "lon": [float, int],
+ "labelrank": [int, float],
+ "middleX": [int, float],
+ "middleY": [int, float],
+ "name": basestring,
+ "path": basestring,
+ "value": [int, float, list],
+ "x": [int, float],
+ "y": [int, float],
+ "z": [float, int],
+ "xAxis": int,
+ "yAxis": int,
+}
+
+DEFAULT_OPTIONS = {
+
+}
+
+class OptionTypeError(Exception):
+
+ def __init__(self, *args):
+ self.args = args
+
+
+class SeriesOptions(object):
+ """Class for plotOptions"""
+
+ def __init__(self, series_type="map", supress_errors=False, **kwargs):
+ self.load_defaults(series_type)
+ self.process_kwargs(kwargs, series_type=series_type, supress_errors=supress_errors)
+
+ @staticmethod
+ def __validate_options__(k, v, ov):
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def __display_options__(self):
+ print(json.dumps(self.__options__(),indent=4,sort_keys=True))
+
+ def update(self,series_type, **kwargs):
+ allowed_args = PLOT_OPTION_ALLOWED_ARGS[series_type]
+ allowed_args.update(PLOT_OPTION_ALLOWED_ARGS["common"])
+
+ for k, v in kwargs.items():
+ if k in allowed_args:
+ if SeriesOptions.__validate_options__(k,v,allowed_args[k]):
+ if isinstance(allowed_args[k], tuple) and isinstance(allowed_args[k][0](), CommonObject):
+ # re-construct input dict with existing options in objects
+ if self.__getattr__(k):
+ if isinstance(v, dict):
+ self.__options__()[k].update(v)
+ else:
+ self.__options__()[k].__options__().update(v)
+ else:
+ self.__options__().update({k:allowed_args[k][0](**v)})
+
+ elif isinstance(allowed_args[k], tuple) and isinstance(allowed_args[k][0](), ArrayObject):
+ # update array
+ if isinstance(v, dict):
+ self.__dict__[k].append(allowed_args[k][0](**v))
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].append(allowed_args[k][0](**item))
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(v))
+
+ elif isinstance(allowed_args[k], tuple) and \
+ (isinstance(allowed_args[k][0](), CSSObject) or isinstance(allowed_args[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items():
+ self.__dict__[k].__options__().update({key:value})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+
+ elif isinstance(allowed_args[k], tuple) and (isinstance(allowed_args[k][0](), JSfunction) or \
+ isinstance(allowed_args[k][0](), Formatter) or isinstance(allowed_args[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ print(k,v)
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % allowed_args[k])
+
+
+ def process_kwargs(self, kwargs, series_type, supress_errors=False):
+ allowed_args = PLOT_OPTION_ALLOWED_ARGS[series_type]
+ allowed_args.update(PLOT_OPTION_ALLOWED_ARGS["common"])
+
+ for k, v in kwargs.items():
+ if k in allowed_args:
+ if SeriesOptions.__validate_options__(k,v,allowed_args[k]):
+ if isinstance(allowed_args[k], tuple):
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ elif isinstance(v, list):
+ if len(v) == 1:
+ self.__dict__.update({k:allowed_args[k][0](**v[0])})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v[0])})
+ for item in v[1:]:
+ self.__dict__[k].update(item)
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ print(k,v)
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % allowed_args[k])
+
+ def load_defaults(self, series_type):
+ self.process_kwargs(DEFAULT_OPTIONS.get(series_type,{}),series_type)
+
+ def __getattr__(self, item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class Series(object):
+ """Series class for input data """
+
+ def __init__(self, data, series_type="line", supress_errors=False, **kwargs):
+
+ # List of dictionaries. Each dict contains data and properties,
+ # which need to handle before construct the object for series
+ if isinstance(data, list):
+ for item in data:
+ if isinstance(item, dict):
+ for k, v in item.items():
+ if k in DATA_SERIES_ALLOWED_OPTIONS:
+ if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
+ if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
+ if isinstance(v, dict):
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, datetime.datetime):
+ item.update({k:v})
+ else:
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
+ else:
+ item.update({k:v})
+
+ self.__dict__.update({
+ "data": data,
+ "type": series_type,
+ })
+
+ # Series propertie can be input as kwargs, which is handled here
+ for k, v in kwargs.items():
+ if k in DATA_SERIES_ALLOWED_OPTIONS:
+ if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
+ if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
+ if isinstance(v, dict):
+ self.__dict__.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % DATA_SERIES_ALLOWED_OPTIONS[k])
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def __options__(self):
+ return self.__dict__
diff --git a/build/lib/highcharts/highmaps/highmaps.py b/build/lib/highcharts/highmaps/highmaps.py
new file mode 100644
index 0000000..f2f7b91
--- /dev/null
+++ b/build/lib/highcharts/highmaps/highmaps.py
@@ -0,0 +1,499 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import unicode_literals, absolute_import
+from future.standard_library import install_aliases
+install_aliases()
+
+from past.builtins import basestring
+
+from urllib.request import urlopen
+from jinja2 import Environment, PackageLoader
+
+import json, uuid
+import re
+import datetime
+import html
+try:
+ # works with older (3.9 and below) versions, throws an exception with newer (3.10 and above) versions
+ from collections import Iterable
+#if an import error change to trying 3.10 and above notation
+except ImportError:
+ from collections.abc import Iterable
+from .options import BaseOptions, ChartOptions, \
+ ColorsOptions, ColorAxisOptions, CreditsOptions, DrilldownOptions, ExportingOptions, \
+ GlobalOptions, LabelsOptions, LangOptions, \
+ LegendOptions, LoadingOptions, MapNavigationOptions, NavigationOptions, PaneOptions, \
+ PlotOptions, SeriesData, SubtitleOptions, TitleOptions, \
+ TooltipOptions, xAxisOptions, yAxisOptions
+
+from .highmap_types import Series, SeriesOptions
+from .common import Formatter, CSSObject, SVGObject, MapObject, JSfunction, RawJavaScriptText, \
+ CommonObject, ArrayObject, ColorObject
+
+
+
+CONTENT_FILENAME = "./content.html"
+PAGE_FILENAME = "./page.html"
+
+pl = PackageLoader('highcharts.highmaps', 'templates')
+jinja2_env = Environment(lstrip_blocks=True, trim_blocks=True, loader=pl)
+
+template_content = jinja2_env.get_template(CONTENT_FILENAME)
+template_page = jinja2_env.get_template(PAGE_FILENAME)
+
+class Highmap(object):
+ """
+ Highcharts Base class.
+ """
+ #: chart count
+ count = 0
+
+ # this attribute is overriden by children of this
+ # class
+ CHART_FILENAME = None
+ template_environment = Environment(lstrip_blocks=True, trim_blocks=True,
+ loader=pl)
+
+ def __init__(self, **kwargs):
+ """
+ This is the base class for all the charts. The following keywords are
+ accepted:
+ :keyword: **display_container** - default: ``True``
+ """
+ # Set the model
+ self.model = self.__class__.__name__ #: The chart model,
+ self.div_name = kwargs.get("renderTo", "container")
+
+ # An Instance of Jinja2 template
+ self.template_page_highcharts = template_page
+ self.template_content_highcharts = template_content
+
+ # Set Javascript src
+ self.JSsource = [
+ 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
+ 'https://code.highcharts.com/maps/6/highmaps.js',
+ 'https://code.highcharts.com/6/highcharts.js',
+ 'https://code.highcharts.com/maps/6/modules/map.js',
+ 'https://code.highcharts.com/maps/6/modules/data.js',
+ 'https://code.highcharts.com/maps/6/modules/exporting.js'
+ ]
+
+ # set CSS src
+ self.CSSsource = [
+ 'https://www.highcharts.com/highslide/highslide.css',
+ ]
+ # Set data
+ self.data = []
+ self.data_temp = []
+ self.data_is_coordinate = False
+ # Data from jsonp
+ self.jsonp_data_flag = False
+
+ # Set drilldown data
+ self.drilldown_data = []
+ self.drilldown_data_temp = []
+
+ # Map
+ self.mapdata_flag = False
+ self.map = None
+
+ # Jsonp map
+ self.jsonp_map_flag = kwargs.get('jsonp_map_flag', False)
+
+ # Javascript
+ self.jscript_head_flag = False
+ self.jscript_head = kwargs.get('jscript_head', None)
+ self.jscript_end_flag = False
+ self.jscript_end = kwargs.get('jscript_end', None)
+
+ # Accepted keywords
+ self.div_style = kwargs.get('style', '')
+ self.drilldown_flag = kwargs.get('drilldown_flag', False)
+
+ # None keywords attribute that should be modified by methods
+ # We should change all these to _attr
+
+ self._htmlcontent = '' #: written by buildhtml
+ self.htmlheader = ''
+ # Place holder for the graph (the HTML div)
+ # Written by ``buildcontainer``
+ self.container = u''
+ # Header for javascript code
+ self.containerheader = u''
+ # Loading message
+ self.loading = 'Loading....'
+
+
+ # Bind Base Classes to self
+ self.options = {
+ "chart": ChartOptions(),
+ #"colorAxis": # cannot input until there is data, do it later
+ "colors": ColorsOptions(),
+ "credits": CreditsOptions(),
+ #"data": #NotImplemented
+ "drilldown": DrilldownOptions(),
+ "exporting": ExportingOptions(),
+ "labels": LabelsOptions(),
+ "legend": LegendOptions(),
+ "loading": LoadingOptions(),
+ "mapNavigation": MapNavigationOptions(),
+ "navigation": NavigationOptions(),
+ "plotOptions": PlotOptions(),
+ "series": SeriesData(),
+ "subtitle": SubtitleOptions(),
+ "title": TitleOptions(),
+ "tooltip": TooltipOptions(),
+ "xAxis": xAxisOptions(),
+ "yAxis": yAxisOptions(),
+ }
+
+ self.setOptions = {
+ "global": GlobalOptions(),
+ "lang": LangOptions(),
+ }
+
+ self.__load_defaults__()
+
+ # Process kwargs
+ allowed_kwargs = [
+ "width",
+ "height",
+ "renderTo",
+ "backgroundColor",
+ "events",
+ "marginBottom",
+ "marginTop",
+ "marginRight",
+ "marginLeft"
+ ]
+
+ for keyword in allowed_kwargs:
+ if keyword in kwargs:
+ self.options['chart'].update_dict(**{keyword:kwargs[keyword]})
+ # Some Extra Vals to store:
+ self.data_set_count = 0
+ self.drilldown_data_set_count = 0
+
+
+ def __load_defaults__(self):
+ self.options["chart"].update_dict(renderTo='container')
+ self.options["title"].update_dict(text='A New Highchart')
+ self.options["credits"].update_dict(enabled=False)
+
+
+ def add_JSsource(self, new_src):
+ """add additional js script source(s)"""
+ if isinstance(new_src, list):
+ for h in new_src:
+ self.JSsource.append(h)
+ elif isinstance(new_src, basestring):
+ self.JSsource.append(new_src)
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src))
+
+
+ def add_CSSsource(self, new_src):
+ """add additional css source(s)"""
+ if isinstance(new_src, list):
+ for h in new_src:
+ self.CSSsource.append(h)
+ elif isinstance(new_src, basestring):
+ self.CSSsource.append(new_src)
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src))
+
+
+ def add_data_set(self, data, series_type="map", name=None, is_coordinate = False, **kwargs):
+ """set data for series option in highmaps """
+
+ self.data_set_count += 1
+ if not name:
+ name = "Series %d" % self.data_set_count
+ kwargs.update({'name':name})
+
+ if is_coordinate:
+ self.data_is_coordinate = True
+ self.add_JSsource('https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.6/proj4.js')
+ if self.map and not self.data_temp:
+ series_data = Series([], series_type='map', **{'mapData': self.map})
+ series_data.__options__().update(SeriesOptions(series_type='map', **{'mapData': self.map}).__options__())
+ self.data_temp.append(series_data)
+
+ if self.map and 'mapData' in kwargs.keys():
+ kwargs.update({'mapData': self.map})
+
+ series_data = Series(data, series_type=series_type, **kwargs)
+
+ series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__())
+ self.data_temp.append(series_data)
+
+
+ def add_drilldown_data_set(self, data, series_type, id, **kwargs):
+ """set data for drilldown option in highmaps
+ id must be input and corresponding to drilldown arguments in data series
+ """
+ self.drilldown_data_set_count += 1
+ if self.drilldown_flag == False:
+ self.drilldown_flag = True
+
+ kwargs.update({'id':id})
+ series_data = Series(data, series_type=series_type, **kwargs)
+ series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__())
+ self.drilldown_data_temp.append(series_data)
+
+
+ def add_data_from_jsonp(self, data_src, data_name = 'json_data', series_type="map", name=None, **kwargs):
+ """add data directly from a https source
+ the data_src is the https link for data using jsonp
+ """
+ self.jsonp_data_flag = True
+ self.jsonp_data_url = json.dumps(data_src)
+ if data_name == 'data':
+ data_name = 'json_'+ data_name
+ self.jsonp_data = data_name
+ self.add_data_set(RawJavaScriptText(data_name), series_type, name=name, **kwargs)
+
+
+ def add_JSscript(self, js_script, js_loc):
+ """add (highcharts) javascript in the beginning or at the end of script
+ use only if necessary
+ """
+ if js_loc == 'head':
+ self.jscript_head_flag = True
+ if self.jscript_head:
+ self.jscript_head = self.jscript_head + '\n' + js_script
+ else:
+ self.jscript_head = js_script
+ elif js_loc == 'end':
+ self.jscript_end_flag = True
+ if self.jscript_end:
+ self.jscript_end = self.jscript_end + '\n' + js_script
+ else:
+ self.jscript_end = js_script
+ else:
+ raise OptionTypeError("Not An Accepted script location: %s, either 'head' or 'end'"
+ % js_loc)
+
+
+ def add_map_data(self, geojson, **kwargs):
+ self.mapdata_flag = True
+ self.map = 'geojson'
+ self.mapdata = json.dumps(geojson)
+
+ if self.data_is_coordinate:
+ kwargs.update({'mapData': self.map})
+ series_data = Series([], 'map')
+ series_data.__options__().update(SeriesOptions('map', **kwargs).__options__())
+ self.data_temp.append(series_data)
+ elif kwargs:
+ kwargs.update({'mapData': self.map})
+ series_data = Series([], 'map')
+ series_data.__options__().update(SeriesOptions('map', **kwargs).__options__())
+ self.data_temp.append(series_data)
+ elif self.data_temp:
+ self.data_temp[0].__options__().update({'mapData': MapObject(self.map)})
+
+
+ def set_map_source(self, map_src, jsonp_map = False):
+ """set map data
+ use if the mapData is loaded directly from a https source
+ the map_src is the https link for the mapData
+ geojson (from jsonp) or .js formates are acceptable
+ default is js script from highcharts' map collection: https://code.highcharts.com/mapdata/
+ """
+
+ if not map_src:
+ raise OptionTypeError("No map source input, please refer to: https://code.highcharts.com/mapdata/")
+
+ if jsonp_map:
+ self.jsonp_map_flag = True
+ self.map = 'geojson'
+ self.jsonp_map_url = json.dumps(map_src)
+ else:
+ self.add_JSsource(map_src)
+ map_name = self._get_jsmap_name(map_src)
+ self.map = 'geojson'
+ self.jsmap = self.map + ' = Highcharts.geojson(' + map_name + ');'
+ self.add_JSscript('var ' + self.jsmap, 'head')
+
+ if self.data_temp:
+ self.data_temp[0].__options__().update({'mapData': MapObject(self.map)})
+
+ def set_options(self, option_type, option_dict, force_options=False):
+ """set plot options"""
+
+ if force_options: # not to use unless it is really needed
+ self.options[option_type].update(option_dict)
+ elif (option_type == 'yAxis' or option_type == 'xAxis') and isinstance(option_dict, list):
+ self.options[option_type] = MultiAxis(option_type)
+ for each_dict in option_dict:
+ self.options[option_type].update(**each_dict)
+ elif option_type == 'colors':
+ self.options["colors"].set_colors(option_dict) # option_dict should be a list
+ elif option_type == 'colorAxis':
+ self.options.update({'colorAxis': self.options.get('colorAxis', ColorAxisOptions())})
+ self.options[option_type].update_dict(**option_dict)
+ elif option_type in ["global" , "lang"]:
+ self.setOptions[option_type].update_dict(**option_dict)
+ else:
+ self.options[option_type].update_dict(**option_dict)
+
+ def set_dict_options(self, options):
+ """for dictionary-like inputs (as object in Javascript)
+ options must be in python dictionary format
+ """
+ if isinstance(options, dict):
+ for key, option_data in options.items():
+ self.set_options(key, option_data)
+ else:
+ raise OptionTypeError("Not An Accepted Input Format: %s. Must be Dictionary" %type(options))
+
+
+ def _get_jsmap_name(self, url):
+ """return 'name' of the map in .js format"""
+
+ ret = urlopen(url)
+ return ret.read().decode('utf-8').split('=')[0].replace(" ", "") #return the name of map file, Ex. 'Highcharts.maps["xxx/xxx"]'
+
+
+ def buildcontent(self):
+ """build HTML content only, no header or body tags"""
+
+ self.buildcontainer()
+ self.option = json.dumps(self.options, cls = HighchartsEncoder)
+ self.setoption = json.dumps(self.setOptions, cls = HighchartsEncoder)
+ self.data = json.dumps(self.data_temp, cls = HighchartsEncoder)
+
+ if self.drilldown_flag:
+ self.drilldown_data = json.dumps(self.drilldown_data_temp, cls = HighchartsEncoder)
+ self._htmlcontent = self.template_content_highcharts.render(chart=self).encode('utf-8')
+
+
+ def buildhtml(self):
+ """Build the HTML page
+ Create the htmlheader with css / js
+ Create html page
+ """
+ self.buildcontent()
+ self.buildhtmlheader()
+ self.content = self._htmlcontent.decode('utf-8') # need to ensure unicode
+ self._htmlcontent = self.template_page_highcharts.render(chart=self)
+ return self._htmlcontent
+
+ def buildhtmlheader(self):
+ """generate HTML header content"""
+ #Highcharts lib/ needs to make sure it's up to date
+
+ if self.drilldown_flag:
+ self.add_JSsource('https://code.highcharts.com/maps/modules/drilldown.js')
+
+ self.header_css = [
+ '' % h for h in self.CSSsource
+ ]
+
+ self.header_js = [
+ '' % h for h in self.JSsource
+ ]
+
+ self.htmlheader = ''
+ for css in self.header_css:
+ self.htmlheader += css
+ for js in self.header_js:
+ self.htmlheader += js
+
+
+ def buildcontainer(self):
+ """generate HTML div"""
+ if self.container:
+ return
+ # Create HTML div with style
+ if self.options['chart'].width:
+ if str(self.options['chart'].width)[-1] != '%':
+ self.div_style += 'width:%spx;' % self.options['chart'].width
+ else:
+ self.div_style += 'width:%s;' % self.options['chart'].width
+ if self.options['chart'].height:
+ if str(self.options['chart'].height)[-1] != '%':
+ self.div_style += 'height:%spx;' % self.options['chart'].height
+ else:
+ self.div_style += 'height:%s;' % self.options['chart'].height
+
+ self.div_name = self.options['chart'].__dict__['renderTo'] # recheck div name
+ self.container = self.containerheader + \
+ '%s
\n' % (self.div_name, self.div_style, self.loading)
+
+ @property
+ def htmlcontent(self):
+ return self.buildhtml()
+
+ @property
+ def iframe(self):
+ htmlsrcdoc = html.escape(self.htmlcontent)
+ htmlsrcdoc = re.sub('\\n', ' ', htmlsrcdoc)
+ htmlsrcdoc = re.sub(' +', ' ', htmlsrcdoc)
+ width = int(self.options['chart'].__dict__['width']) if self.options['chart'].__dict__.get('width') else 820
+ height = int(self.options['chart'].__dict__['height']) if self.options['chart'].__dict__.get('height') else 520
+
+ if self.options['chart'].__dict__.get('options3d'):
+ if len(htmlsrcdoc) < 99965000 :
+ return ''
+ else:
+ return ''
+ else:
+ return ''
+
+ def __str__(self):
+ """return htmlcontent"""
+ #self.buildhtml()
+ return self.htmlcontent
+
+ def save_file(self, filename = 'Map'):
+ """ save htmlcontent as .html file """
+ filename = filename + '.html'
+
+ with open(filename, 'w') as f:
+ #self.buildhtml()
+ f.write(self.htmlcontent)
+
+ f.closed
+
+class HighchartsEncoder(json.JSONEncoder):
+ def __init__(self, *args, **kwargs):
+ json.JSONEncoder.__init__(self, *args, **kwargs)
+ self._replacement_map = {}
+
+ def default(self, obj):
+ if isinstance(obj, RawJavaScriptText):
+ key = uuid.uuid4().hex
+ self._replacement_map[key] = obj.get_jstext()
+ return key
+ elif isinstance(obj, datetime.datetime):
+ utc = obj.utctimetuple()
+ obj = (u"Date.UTC({year},{month},{day},{hours},{minutes},{seconds},{millisec})"
+ .format(year=utc[0], month=utc[1]-1, day=utc[2], hours=utc[3],
+ minutes=utc[4], seconds=utc[5], millisec=obj.microsecond/1000))
+ return RawJavaScriptText(obj)
+ elif isinstance(obj, BaseOptions):
+ return obj.__jsonable__()
+ elif isinstance(obj, CSSObject) or isinstance(obj, Formatter) or isinstance(obj, JSfunction) \
+ or isinstance(obj, MapObject):
+ return obj.__jsonable__()
+ elif isinstance(obj, SeriesOptions) or isinstance(obj, Series):
+ return obj.__jsonable__()
+ elif isinstance(obj, CommonObject) or isinstance(obj, ArrayObject) or isinstance(obj, ColorObject):
+ return obj.__jsonable__()
+ else:
+ return json.JSONEncoder.default(self, obj)
+
+ def encode(self, obj):
+ result = json.JSONEncoder.encode(self, obj)
+ for k, v in self._replacement_map.items():
+ result = result.replace('"%s"' % (k,), v)
+ return result
+
+
+class OptionTypeError(Exception):
+
+ def __init__(self,*args):
+ self.args = args
diff --git a/build/lib/highcharts/highmaps/options.py b/build/lib/highcharts/highmaps/options.py
new file mode 100644
index 0000000..471fdd8
--- /dev/null
+++ b/build/lib/highcharts/highmaps/options.py
@@ -0,0 +1,534 @@
+# -*- coding: UTF-8 -*-
+from past.builtins import basestring
+
+from .highmap_types import OptionTypeError, Series, SeriesOptions
+from .common import Formatter, Events, Position, ContextButton, Button, Options3d, ResetZoomButton, \
+ DrillUpButton, Labels, DataClasses, Title, Items, Navigation, Background, Breaks, Marker, \
+ DateTimeLabelFormats, JSfunction, ColorObject, CSSObject, SVGObject, CommonObject, ArrayObject
+
+import json, datetime
+
+# Base Option Class
+class BaseOptions(object):
+
+ def __init__(self, **kwargs):
+ self.update_dict(**kwargs)
+
+ def __display_options__(self):
+ print(json.dumps(self.__dict__, indent=4, sort_keys=True))
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def __validate_options__(self, k, v, ov):
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,dict) and isinstance(ov,dict):
+ keys = v.keys()
+ if len(keys) > 1:
+ raise NotImplementedError
+ return isinstance(v[keys[0]],ov[keys[0]])
+ return isinstance(v, ov)
+
+ def update_dict(self, **kwargs):
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ # if isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), SeriesOptions):
+ if k in PlotOptions.ALLOWED_OPTIONS.keys():
+ if self.__getattr__(k):
+ self.__dict__[k].update(series_type=k, **v)
+ else:
+ v = SeriesOptions(series_type=k, **v)
+ self.__dict__.update({k:v})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), CommonObject):
+ if isinstance(v, dict):
+ if self.__getattr__(k):
+ self.__dict__[k].update(v) #update dict
+ else: # first
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be dictionary" % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), ArrayObject):
+ if self.__getattr__(k): #existing attr
+ if isinstance(v, dict):
+ self.__dict__[k].update(v) # update array
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].update(item) # update array
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be list or dictionary"
+ % type(v))
+ else: #first
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, list):
+ if len(v) == 1:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v[0])})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v[0])})
+ for item in v[1:]:
+ self.__dict__[k].update(item)
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be list or dictionary"
+ % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ (isinstance(self.ALLOWED_OPTIONS[k][0](), CSSObject) or isinstance(self.ALLOWED_OPTIONS[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items(): # check if v has object input
+ self.__dict__[k].__options__().update({key:value})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and (isinstance(self.ALLOWED_OPTIONS[k][0](), JSfunction) or \
+ isinstance(self.ALLOWED_OPTIONS[k][0](), Formatter) or isinstance(self.ALLOWED_OPTIONS[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+
+ else:
+ print(self.ALLOWED_OPTIONS)
+ print(k, v)
+ raise OptionTypeError("Not An Accepted Option Type: %s" % k)
+
+
+ def __getattr__(self, item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class ChartOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "animation": [bool, dict, basestring],
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": [int, float],
+ "borderWidth": [int, float],
+ "className": basestring,
+ "events": (Events, dict),
+ "height": [int,basestring],
+ "margin": list,
+ "marginBottom": int,
+ "marginLeft": int,
+ "marginRight": int,
+ "marginTop": int,
+ "plotBackgroundColor": (ColorObject, basestring, dict),
+ "plotBackgroundImage": basestring,
+ "plotBorderColor": (ColorObject, basestring, dict),
+ "plotBorderWidth": [int, float],
+ "plotShadow": bool,
+ "reflow": bool,
+ "renderTo": basestring,
+ "resetZoomButton": (ResetZoomButton, dict),
+ "selectionMarkerFill": basestring,
+ "shadow": bool,
+ "spacing": list,
+ "spacingBottom": int,
+ "spacingLeft": int,
+ "spacingRight": int,
+ "spacingTop": int,
+ "style": (CSSObject, dict),
+ "type": basestring,
+ "width": [int,basestring],
+ }
+
+class ColorAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "dataClassColor": basestring,
+ "dataClasses": (DataClasses, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineWidth": [float, int],
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": [float, int],
+ "marker": (Marker, dict),
+ "max": [float, int],
+ "maxColor": (ColorObject, basestring, dict),
+ "maxPadding": [float, int],
+ "min": [float, int],
+ "minColor": (ColorObject, basestring, dict),
+ "minPadding": [float, int],
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "reversed": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "stops": list,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": JSfunction,
+ "tickPositions": list,
+ "tickWidth": int,
+ "type": basestring,
+}
+
+
+class ColorsOptions(BaseOptions):
+ """ Special Case, this is simply just an array of colours """
+ def __init__(self):
+ self.colors = {}
+
+ def set_colors(self, colors):
+ if isinstance(colors, basestring):
+ self.colors = ColorObject(colors)
+ elif isinstance(colors, list) or isinstance(colors, dict):
+ self.colors = colors
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(colors))
+
+ def __jsonable__(self):
+ return self.colors
+
+
+class CreditsOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "href": basestring,
+ "position": (Position, dict),
+ "style": (CSSObject, dict),
+ "text": basestring,
+ }
+
+
+class DrilldownOptions(BaseOptions): #not implement yet, need work in jinjia
+ ALLOWED_OPTIONS = {
+ "activeAxisLabelStyle": (CSSObject, dict),
+ "activeDataLabelStyle": (CSSObject, dict),
+ "animation": NotImplemented, #(bool, dict), #not sure how to implement
+ "drillUpButton": (DrillUpButton, dict),
+ "series": (Series, dict),
+ }
+
+
+class ExportingOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "buttons": (ContextButton, dict),
+ "chartOptions": (ChartOptions, dict),
+ "enabled": bool,
+ "filename": basestring,
+ "formAttributes": NotImplemented,
+ "scale": int,
+ "sourceHeight": int,
+ "sourceWidth": int,
+ "type": basestring,
+ "url": basestring,
+ "width": int,
+ }
+
+
+class GlobalOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "Date": NotImplemented,
+ "VMLRadialGradientURL": basestring,
+ "canvasToolsURL": basestring,
+ "getTimezoneOffset": (JSfunction, basestring),
+ "timezoneOffset": int,
+ "useUTC": bool,
+ }
+
+
+class LabelsOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "items": (Items, dict),
+ "style": (CSSObject, dict),
+ }
+
+
+class LangOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "decimalPoint": basestring,
+ "downloadJPEG": basestring,
+ "downloadPDF": basestring,
+ "downloadPNG": basestring,
+ "donwloadSVG": basestring,
+ "exportButtonTitle": basestring,
+ "loading": basestring,
+ "months": list,
+ "noData": basestring,
+ "numericSymbols": list,
+ "printButtonTitle": basestring,
+ "resetZoom": basestring,
+ "resetZoomTitle": basestring,
+ "shortMonths": list,
+ "thousandsSep": basestring,
+ "weekdays": list,
+ }
+
+
+class LegendOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": [int, float],
+ "borderWidth": [int, float],
+ "enabled": bool,
+ "floating": bool,
+ "itemDistance": int,
+ "itemHiddenStyle": (CSSObject, dict),
+ "itemHoverStyle": (CSSObject, dict),
+ "itemMarginBottom": int,
+ "itemMarginTop": int,
+ "itemStyle": (CSSObject, dict),
+ "itemWidth": int,
+ "labelFormat": basestring,
+ "labelFormatter": (Formatter, JSfunction),
+ "layout": basestring,
+ "lineHeight": int,
+ "margin": int,
+ "maxHeight": int,
+ "navigation": (Navigation, dict),
+ "padding": int,
+ "reversed": bool,
+ "rtl": bool,
+ "shadow": bool,
+ "style": (CSSObject, dict),
+ "symbolHeight": int,
+ "symbolPadding": int,
+ "symbolRadius": int,
+ "symbolWidth": int,
+ "title": (Title, dict),
+ "useHTML": bool,
+ "valueDecimals": int,
+ "valueSuffix": basestring,
+ "verticalAlign": basestring,
+ "width": int,
+ "x": int,
+ "y": int,
+
+ }
+
+
+class LoadingOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "hideDuration": int,
+ "labelStyle": (CSSObject, dict),
+ "showDuration": int,
+ "style": (CSSObject, dict),
+ }
+
+
+class MapNavigationOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "buttonOptions": (ContextButton, dict),
+ "buttons": (Button, dict),
+ "enableButtons": bool,
+ "enableDoubleClickZoom": bool,
+ "enableDoubleClickZoomTo": bool,
+ "enableMouseWheelZoom": bool,
+ "enableTouchZoom": bool,
+ "enabled": bool,
+ }
+
+class NavigationOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "buttonOptions": (ContextButton, dict),
+ "menuItemHoverStyle": (CSSObject, dict),
+ "menuItemStyle": (CSSObject, dict),
+ "menuStyle": (CSSObject, dict),
+ }
+
+
+class PaneOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "background": (Background, list), #arrayObject
+ "center": list,
+ "endAngle": int,
+ "size": int,
+ "startAngle": int,
+ }
+
+
+class PlotOptions(BaseOptions):
+ """ Another Special Case: Interface With all the different Highchart Plot Types Here """
+ ALLOWED_OPTIONS = {
+ "heatmap": (SeriesOptions, dict),
+ "map": (SeriesOptions, dict),
+ "mapbubble": (SeriesOptions, dict),
+ "mapline": (SeriesOptions, dict),
+ "mappoint": (SeriesOptions, dict),
+ "series": (SeriesOptions, dict),
+ }
+
+
+class SeriesData(BaseOptions):
+ """ Another Special Case: Stores Data Series in an array for returning to the chart object """
+ def __init__(self):
+ #self.__dict__.update([])
+ self = []
+
+
+class SubtitleOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "floating": bool,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+
+class TitleOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "floating": bool,
+ "margin": int,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+
+class TooltipOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "animation": bool,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": [int, float],
+ "borderWidth": [int, float],
+ "crosshairs": [bool, list, dict],
+ "enabled": bool,
+ "followPointer": bool,
+ "followTouchMove": bool,
+ "footerFormat": basestring,
+ "formatter": (Formatter, JSfunction),
+ "headerFormat": basestring,
+ "pointFormat": basestring,
+ "positioner": (JSfunction, basestring),
+ "shadow": bool,
+ "style": (CSSObject, dict),
+ "useHTML": bool,
+ "valueDecimals": int,
+ "valuePrefix": basestring,
+ "valueSuffix": basestring,
+ }
+
+
+class xAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "allowDecimals": bool,
+ "alternateGridColor": (ColorObject, basestring, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineWidth": int,
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": int,
+ "max": [float, int],
+ "maxPadding": [float, int],
+ "min": [float, int],
+ "minPadding": [float, int],
+ "minRange": int,
+ "minTickInterval": int,
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "offset": bool,
+ "opposite": bool,
+ "reversed": bool,
+ "showEmpty": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "startOnTick": bool,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": JSfunction,
+ "tickPositions": list,
+ "tickWidth": int,
+ "title": (Title, dict),
+ }
+
+
+class yAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "allowDecimals": bool,
+ "alternateGridColor": (ColorObject, basestring, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "floor": (int, float),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineWidth": int,
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "max": [float, int],
+ "maxColor": (ColorObject, basestring, dict),
+ "maxPadding": [float, int],
+ "min": [float, int],
+ "minColor": (ColorObject, basestring, dict),
+ "minPadding": [float, int],
+ "minRange": int,
+ "minTickInterval": int,
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "offset": bool,
+ "opposite": bool,
+ "reversed": bool,
+ "showEmpty": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "startOnTick": bool,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": (JSfunction, basestring),
+ "tickPositions": list,
+ "tickWidth": int,
+ "title": (Title, dict),
+ }
+
\ No newline at end of file
diff --git a/build/lib/highcharts/highmaps/templates/base.html b/build/lib/highcharts/highmaps/templates/base.html
new file mode 100644
index 0000000..af25a2b
--- /dev/null
+++ b/build/lib/highcharts/highmaps/templates/base.html
@@ -0,0 +1,21 @@
+{% block container %}
+{% endblock %}
+
+{% block start_script %}
+
+{% endblock endscript %}
diff --git a/build/lib/highcharts/highmaps/templates/content.html b/build/lib/highcharts/highmaps/templates/content.html
new file mode 100644
index 0000000..f0f6a95
--- /dev/null
+++ b/build/lib/highcharts/highmaps/templates/content.html
@@ -0,0 +1,57 @@
+{% extends "base.html" %}
+{% block container %}
+ {{ chart.container }}
+{% endblock container %}
+
+{% block body_head %}
+
+ {% if chart.jsonp_map_flag %}
+ $.getJSON({{chart.jsonp_map_url}}, function ({{chart.map}})
+ {
+ {% endif %}
+ {% if chart.jsonp_data_flag %}
+ $.getJSON({{chart.jsonp_data_url}}, function ({{chart.jsonp_data}})
+ {
+ {% endif %}
+
+{% endblock body_head %}
+
+{% block body_content %}
+
+ {% if chart.jscript_head_flag %}
+ {{chart.jscript_head}}
+ {% endif %}
+
+ Highcharts.setOptions({{chart.setoption}});
+ var option = {{chart.option}};
+
+ {% if chart.mapdata_flag %}
+ var geojson = {{chart.mapdata}}
+ {% endif %}
+
+ var data = {{chart.data}};
+ option.series = data;
+
+ {% if chart.drilldown_flag %}
+ var drilldowndata = {{chart.drilldown_data}};
+ option.drilldown.series = drilldowndata;
+ {% endif %}
+
+ var chart = new Highcharts.Map(option);
+
+ {% if chart.jscript_end_flag %}
+ {{chart.jscript_end}}
+ {% endif %}
+
+{% endblock body_content %}
+
+{% block body_end %}
+
+ {% if chart.jsonp_map_flag %}
+ });
+ {% endif %}
+ {% if chart.jsonp_data_flag %}
+ });
+ {% endif %}
+
+{% endblock body_end %}
diff --git a/build/lib/highcharts/highmaps/templates/page.html b/build/lib/highcharts/highmaps/templates/page.html
new file mode 100644
index 0000000..3559aaa
--- /dev/null
+++ b/build/lib/highcharts/highmaps/templates/page.html
@@ -0,0 +1,12 @@
+
+
+
+
+ {% for header_element in chart.header_css+chart.header_js %}
+ {{ header_element }}
+ {% endfor %}
+
+
+ {{ chart.content }}
+
+
diff --git a/build/lib/highcharts/highmaps/templates/test.html b/build/lib/highcharts/highmaps/templates/test.html
new file mode 100644
index 0000000..63eecc5
--- /dev/null
+++ b/build/lib/highcharts/highmaps/templates/test.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ {{ chart.title }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/lib/highcharts/highstock/__init__.py b/build/lib/highcharts/highstock/__init__.py
new file mode 100644
index 0000000..1fa7336
--- /dev/null
+++ b/build/lib/highcharts/highstock/__init__.py
@@ -0,0 +1 @@
+from .highstock import Highstock
\ No newline at end of file
diff --git a/build/lib/highcharts/highstock/common.py b/build/lib/highcharts/highstock/common.py
new file mode 100644
index 0000000..ea43dc7
--- /dev/null
+++ b/build/lib/highcharts/highstock/common.py
@@ -0,0 +1,729 @@
+# -*- coding: UTF-8 -*-
+""" Python-Highstock common.py
+Common Functions For Highstock
+"""
+from past.builtins import basestring
+import datetime, re
+
+FORMATTER_TYPE_MAPPINGS = {
+ "default": "function() { return this.value }",
+ "date": "function() { return''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + ': '+ this.y; }",
+ "pie": "function() { return ''+ this.point.name +': '+ \
+ this.percentage +' %'; }",
+ "pound_yAxis": "function() { '£' + return this.value }",
+ "pound_tooltip": "function() { return''+ this.x + ': '+ '£' +this.y; }",
+ "percent": "function() { return this.value + ' %' }",
+ "default_tooltip": "function () { return''+ this.series.name + ': ' + this.y; }",
+ "percent_tooltip": "function () { return''+ this.series.name + ': ' + this.y + ' %'; }",
+ "date_percent_tooltip": "function () { return''+Highcharts.dateFormat('%e. %b %Y',this.x) + '
'+ this.series.name + ': ' + this.y + ' %'; }",
+ 'filesize': """
+function() {
+ fileSizeInBytes = this.value;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'date_filesize_tooltip': """
+function() {
+ fileSizeInBytes = this.y;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return ''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + '
' + this.series.name + ': ' + Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'filesize_tooltip': """
+function() {
+ fileSizeInBytes = this.y;
+ var i = -1;
+ var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+ do {
+ fileSizeInBytes = fileSizeInBytes / 1024;
+ i++;
+ } while (fileSizeInBytes > 1024);
+
+ return '' + this.series.name + ': ' + Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+}
+""",
+ 'duration': """
+function() {
+ seconds = this.value;
+
+ days = Math.floor(seconds / 86400);
+ seconds = seconds - (days * 86400);
+
+ hours = Math.floor(seconds / 3600);
+ seconds = seconds - (hours * 3600);
+
+ mins = Math.floor(seconds / 60);
+ seconds = seconds - (mins * 60);
+
+ res = "";
+ if(days > 0){
+ res += days + " d ";
+ }
+ if(hours > 0){
+ res += hours + ' hr ';
+ }
+ if(mins > 0){
+ res += mins + ' m ';
+ }
+ if(seconds > 0){
+ res += seconds + ' s ';
+ }
+ return res;
+}
+""",
+ 'date_duration_tooltip': """
+function() {
+ seconds = this.y;
+
+ days = Math.floor(seconds / 86400);
+ seconds = seconds - (days * 86400);
+
+ hours = Math.floor(seconds / 3600);
+ seconds = seconds - (hours * 3600);
+
+ mins = Math.floor(seconds / 60);
+ seconds = seconds - (mins * 60);
+
+ res = "";
+ if(days > 0){
+ res += days + " d ";
+ }
+ if(hours > 0){
+ res += hours + ' hr ';
+ }
+ if(mins > 0){
+ res += mins + ' m ';
+ }
+ if(seconds > 0){
+ res += seconds + ' s ';
+ }
+ return ''+Highcharts.dateFormat('%e. %b %Y %H:%M:%S',this.x) + '
'+ this.series.name + ': ' + res;
+}
+""",
+}
+
+REGEX_LIST = {
+ "re_funct" : re.compile(r'.*function\(.*\)\{.*\}', re.I), #for inputs such as function(xxx){xxx}
+ "re_hcharts" : re.compile(r'.*Highcharts.*', re.I), #for inputs such as highcharts.xxxxx
+}
+
+
+class Formatter(object):
+ """ Base Formatter Class """
+
+ def __init__(self, format=None):
+ ### Choose either from default functions in FORMATTER_TYPE_MAPPINGS using format_type
+ ### or wriet a function in format_string
+ if format:
+ if format in FORMATTER_TYPE_MAPPINGS:
+ self.formatter = RawJavaScriptText(FORMATTER_TYPE_MAPPINGS[format])
+ elif isinstance(format, basestring):
+ self.formatter = RawJavaScriptText(format)
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % basestring)
+
+ def __options__(self):
+ return self.formatter
+
+ def __jsonable__(self):
+ return self.formatter
+
+class ColorObject(object):
+ """ color object """
+
+ def __init__(self, color = None, **kwargs):
+ if not color:
+ color = kwargs
+
+ if color:
+ if isinstance(color, dict):
+ tmp = []
+ for i, item in enumerate(color['stops']):
+ tmp.append([RawJavaScriptText(x) if isinstance(x, basestring) and any([REGEX_LIST[key].search(x) for key in REGEX_LIST.keys()])
+ else x for x in item ])
+ color['stops'] = tmp
+ self.color = color
+ elif any([REGEX_LIST[key].search(color) for key in REGEX_LIST.keys()]):
+ self.color = RawJavaScriptText(color)
+ elif isinstance(color, basestring):
+ self.color = color
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % (basestring or dict))
+ else:
+ self.color = None
+
+ def __options__(self):
+ return self.color
+
+ def __jsonable__(self):
+ return self.color
+
+
+class CSSObject(object):
+ """ CSS style class """
+ ALLOWED_OPTIONS = {}
+ def __init__(self, **kwargs):
+ self.css = kwargs
+
+ for k, v in self.css.items():
+ if isinstance(v, basestring) and any([REGEX_LIST[key].search(v) for key in REGEX_LIST.keys()]):
+ v = RawJavaScriptText(v)
+ self.css.update({k:v})
+
+ def __options__(self):
+ return self.css
+
+ def __jsonable__(self):
+ return self.css
+
+
+class SVGObject(object):
+ """ SVG style class """
+
+ def __init__(self, **kwargs):
+ self.svg = kwargs
+
+ for k, v in self.svg.items():
+ if isinstance(v, basestring) and any([REGEX_LIST[key].search(v) for key in REGEX_LIST.keys()]):
+ v = RawJavaScriptText(v)
+ self.svg.update({k:v})
+
+ def __options__(self):
+ return self.svg
+
+ def __jsonable__(self):
+ return self.svg
+
+
+class JSfunction(object):
+
+ def __init__(self, function = None):
+ if function:
+ if isinstance(function, basestring):
+ self.function = RawJavaScriptText(function)
+ elif isinstance(function, JSfunction):
+ self.function = function
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % basestring)
+
+
+ def __options__(self):
+ return self.function
+
+ def __jsonable__(self):
+ return self.function
+
+
+class RawJavaScriptText:
+
+ def __init__(self, jstext):
+ self._jstext = jstext
+ def get_jstext(self):
+ return self._jstext
+
+
+class CommonObject(object):
+
+ def __init__(self, **kwargs):
+ self.process_kwargs(kwargs)
+
+ def __validate_options__(self, k, v, ov):
+
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def update(self, kwargs):
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), CommonObject):
+ # re-construct input dict with existing options in objects
+ if self.__getattr__(k):
+ if isinstance(v, dict):
+ self.__options__()[k].update(v)
+ else:
+ self.__options__()[k].__options__().update(v)
+ else:
+ self.__options__().update({k:allowed_args[k][0](**v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), ArrayObject):
+ # update array
+ if isinstance(v, dict):
+ self.__dict__[k].append(self.ALLOWED_OPTIONS[k][0](**v))
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].append(self.ALLOWED_OPTIONS[k][0](**item))
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ (isinstance(self.ALLOWED_OPTIONS[k][0](), CSSObject) or isinstance(self.ALLOWED_OPTIONS[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items():
+ self.__dict__[k].__options__().update({key:value})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and (isinstance(self.ALLOWED_OPTIONS[k][0](), JSfunction) or
+ isinstance(self.ALLOWED_OPTIONS[k][0](), Formatter) or isinstance(self.ALLOWED_OPTIONS[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+
+ else:
+ raise OptionTypeError("Not An Accepted Option Type: %s" % k)
+
+ def process_kwargs(self, kwargs):
+
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if self.__validate_options__(k,v,self.ALLOWED_OPTIONS[k]):
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ self.ALLOWED_OPTIONS[k][0] in IDV_OBJECT_LIST:
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % self.ALLOWED_OPTIONS[k])
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Event Class:" % k)
+
+ def __getattr__(self, item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class Events(CommonObject):
+ """ Class for event listener """
+
+ ALLOWED_OPTIONS = {
+ "addSeries": (JSfunction, basestring),
+ "afterPrint": (JSfunction, basestring),
+ "afterBreaks": (JSfunction, basestring),
+ "afterSetExtremes": (JSfunction, basestring),
+ "afterAnimate": (JSfunction, basestring),
+ "beforePrint": (JSfunction, basestring),
+ "checkboxClick": (JSfunction, basestring),
+ "click": (JSfunction, basestring),
+ "drilldown": (JSfunction, basestring),
+ "drillup": (JSfunction, basestring),
+ "load": (JSfunction, basestring),
+ "hide": (JSfunction, basestring),
+ "legendItemClick": (JSfunction, basestring),
+ "mouseOut": (JSfunction, basestring),
+ "mouseOver": (JSfunction, basestring),
+ "pointBreak": (JSfunction, basestring),
+ "remove": (JSfunction, basestring),
+ "redraw": (JSfunction, basestring),
+ "selection": (JSfunction, basestring),
+ "show": (JSfunction, basestring),
+ "select": (JSfunction, basestring),
+ "unselect": (JSfunction, basestring),
+ "update": (JSfunction, basestring),
+ "setExtremes": (JSfunction, basestring)
+ }
+
+class Point(CommonObject):
+ ALLOWED_OPTIONS = {
+ "events": Events
+ }
+
+class Position(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+class ContextButton(CommonObject):
+ """ Option class for the export button """
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "enabled": bool,
+ "height": int,
+ "menuItems": NotImplemented,
+ "onclick": (JSfunction, basestring),
+ "symbol": basestring,
+ "symbolFill": basestring,
+ "symbolSize": int,
+ "symbolStroke": basestring,
+ "symbolStrokeWidth": int,
+ "symbolX": [float, int],
+ "symbolY": [float, int],
+ "text": basestring,
+ "theme": NotImplemented,#ThemeObject
+ "verticalAlign": basestring,
+ "width": int,
+ "x": int,
+ "y": int,
+ }
+
+class Options3d(CommonObject):
+ ALLOWED_OPTIONS = {
+ "alpha": [float, int],
+ "beta": [float, int],
+ "depth": int,
+ "enabled": bool,
+ "frame": NotImplemented, # FrameObject
+ "viewDistance": int
+ }
+
+
+class ResetZoomButton(CommonObject):
+ ALLOWED_OPTIONS = {
+ "position": (Position, dict),
+ "relativeTo": basestring,
+ "theme": NotImplemented #ThemeObject
+ }
+
+class Labels(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": [float, int],
+ "borderWidth": [int, basestring],
+ "color": (ColorObject, basestring, dict),
+ "connectorColor": (ColorObject, basestring, dict),
+ "connectorPadding": [float, int],
+ "connectorWidth": [float, int],
+ "crop": bool,
+ "defer": bool,
+ "distance": int,
+ "enabled": bool,
+ "format": basestring,
+ "formatter": (Formatter, JSfunction, basestring),
+ "inside": bool,
+ "overflow": basestring,
+ "padding": [float, int],
+ "rotation": int,
+ "shadow": [bool, dict], #shadow object
+ "shape": basestring,
+ "softConnector": bool,
+ "staggerLines": int,
+ "step": int,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "textAlign": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ "zIndex": int,
+ }
+
+class Title(CommonObject):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "enabled": bool,
+ "margin": int,
+ "offset": int,
+ "rotation": int,
+ "style": (CSSObject, dict),
+ "text": [basestring, type(None)]
+ }
+
+class Navigation(CommonObject):
+ ALLOWED_OPTIONS = {
+ "activeColor": (ColorObject, basestring, dict),
+ "animation": NotImplemented,
+ "arrowSize": int,
+ "inactiveColor": (ColorObject, basestring, dict),
+ "style": (CSSObject, dict),
+ }
+
+class Handles(CommonObject):
+ ALLOWED_OPTIONS = {
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ }
+
+class DateTimeLabelFormats(CommonObject):
+ ALLOWED_OPTIONS = {
+ "millisecond": basestring,
+ "second": basestring,
+ "minute": basestring,
+ "hour": basestring,
+ "day": basestring,
+ "week": basestring,
+ "month": basestring,
+ "year": basestring,
+ }
+
+class DataGrouping(CommonObject):
+ ALLOWED_OPTIONS = {
+ "approximation": (JSfunction, basestring),
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "enabled": bool,
+ "forced": bool,
+ "groupPixelWidth": [int, float],
+ "smoothed": bool,
+ "units": list,
+ }
+
+class Select(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "radius": int,
+ }
+
+class States(CommonObject):
+ ALLOWED_OPTIONS = {
+ "hover": dict,
+ "select": dict,
+ }
+
+class Marker(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "height": int,
+ "lineWidth": int,
+ "lineColor": (ColorObject, basestring, dict),
+ "radius": int,
+ "states": (States, dict),
+ "symbol": basestring,
+ "width": int
+ }
+
+class Halo(CommonObject):
+ ALLOWED_OPTIONS = {
+ "attributes": (SVGObject, dict),
+ "opacity": float,
+ "size": int
+ }
+
+class Hover(CommonObject):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "fillColor": (ColorObject, basestring, dict),
+ "halo": (Halo, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "lineWidthPlus": int,
+ "marker": (Marker, dict),
+ "radius": int,
+ "radiusPlus": int,
+ }
+
+class States(CommonObject):
+ ALLOWED_OPTIONS = {
+ "hover": (Hover, dict),
+ "select": (Select, dict)
+ }
+
+class Tooltip(CommonObject):
+ ALLOWED_OPTIONS = {
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "followPointer": bool,
+ "followTouchMove": bool,
+ "footerFormat": basestring,
+ "headerFormat": basestring,
+ "hideDelay": int,
+ "pointFormat": basestring,
+ "pointFormatter": (Formatter, JSfunction, basestring),
+ "shape": basestring,
+ "valueDecimals": int,
+ "valuePrefix": basestring,
+ "valueSuffix": basestring,
+ "xDateFormat": basestring
+ }
+
+class Shadow(CommonObject):
+ # not in use yet... not sure hot wo implement
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, dict),
+ "offsetX": [int, float],
+ "offsetY": [int, float],
+ "opacity": [int, float],
+ "width": [int, float],
+ }
+
+class ArrayObject(object):
+
+ def __init__(self, **kwargs):
+ self.data =[]
+ self.process_kwargs(kwargs)
+
+ def __validate_options__(self, k,v,ov):
+
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.data
+
+ def __jsonable__(self):
+ return self.data
+
+ def update(self, kwargs):
+ self.process_kwargs(kwargs)
+
+ def process_kwargs(self, kwargs):
+ temp = {}
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ if self.__validate_options__(k,v,self.ALLOWED_OPTIONS[k]):
+ if isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ self.ALLOWED_OPTIONS[k][0] in IDV_OBJECT_LIST:
+ if isinstance(v, dict):
+ temp.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ temp.update({k:v})
+ else:
+ temp.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ temp.update({k:v})
+ else:
+ raise OptionTypeError("Option Type Mismatch: Expected: %s" % self.ALLOWED_OPTIONS[k])
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Event Class:" % k)
+ self.data.append(temp)
+
+class PlotBands(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, basestring],
+ "color": (ColorObject, basestring, dict),
+ "events": (Events, dict),
+ "from": [int, float, datetime.datetime],
+ "id": basestring,
+ "label": (Labels, dict),
+ "to": [int, float, datetime.datetime],
+ "zIndex": int
+ }
+
+class PlotLines(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "dashStyle": int,
+ "events": (Events, dict),
+ "id": basestring,
+ "label": (Labels, dict),
+ "value": [int, float],
+ "width": int,
+ "zIndex": int
+ }
+
+class Items(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "html": basestring,
+ "style": (CSSObject, dict)
+ }
+
+class Background(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderWidth": [int, basestring],
+ "borderColor": (ColorObject, basestring, dict),
+ "innerWidth": int,
+ "outerWidth": int,
+ "outerRadius": basestring,
+ "shape": basestring,
+ }
+
+class Breaks(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "breakSize": int,
+ "from": [int, float, datetime.datetime],
+ "repeat": int,
+ "to": [int, float, datetime.datetime],
+ }
+
+class Buttons(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "type": basestring,
+ "count": [int, float],
+ "text": basestring,
+ }
+
+class Zones(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "value": [int, float],
+ }
+
+class Levels(ArrayObject):
+ ALLOWED_OPTIONS = {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderDashStyle": basestring,
+ "borderWidth": [int, basestring],
+ "color": (ColorObject, basestring, dict),
+ "dataLabels": (Labels, dict),
+ "layoutAlgorithm": basestring,
+ "layoutStartingDirection": basestring,
+ "level": int,
+ }
+
+
+IDV_OBJECT_LIST = [JSfunction, Formatter, Halo, Marker, Labels,
+ Position, Hover, Select, Events, States, ContextButton,
+ CSSObject, SVGObject, ColorObject,
+ RawJavaScriptText, DateTimeLabelFormats]
+
+
+class OptionTypeError(Exception):
+
+ def __init__(self, *args):
+ self.args = args
diff --git a/build/lib/highcharts/highstock/highstock.py b/build/lib/highcharts/highstock/highstock.py
new file mode 100644
index 0000000..9b38c2f
--- /dev/null
+++ b/build/lib/highcharts/highstock/highstock.py
@@ -0,0 +1,440 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import unicode_literals, absolute_import
+from future.standard_library import install_aliases
+install_aliases()
+
+from jinja2 import Environment, PackageLoader
+
+import json, uuid
+import re
+import datetime
+import html
+try:
+ # works with older (3.9 and below) versions, throws an exception with newer (3.10 and above) versions
+ from collections import Iterable
+#if an import error change to trying 3.10 and above notation
+except ImportError:
+ from collections.abc import Iterable
+from .options import BaseOptions, ChartOptions, \
+ ColorsOptions, CreditsOptions, ExportingOptions, \
+ GlobalOptions, LabelsOptions, LangOptions, \
+ LegendOptions, LoadingOptions, NavigatorOptions, NavigationOptions, \
+ PlotOptions, RangeSelectorOptions, ScrollbarOptions, SeriesData, SubtitleOptions, TitleOptions, \
+ TooltipOptions, xAxisOptions, yAxisOptions, MultiAxis
+
+from .highstock_types import Series, SeriesOptions
+from .common import Levels, Formatter, CSSObject, SVGObject, JSfunction, RawJavaScriptText, \
+ CommonObject, ArrayObject, ColorObject
+
+CONTENT_FILENAME = "./content.html"
+PAGE_FILENAME = "./page.html"
+
+pl = PackageLoader('highcharts.highstock', 'templates')
+jinja2_env = Environment(lstrip_blocks=True, trim_blocks=True, loader=pl)
+
+template_content = jinja2_env.get_template(CONTENT_FILENAME)
+template_page = jinja2_env.get_template(PAGE_FILENAME)
+
+
+class Highstock(object):
+ """
+ Highstock Base class.
+ """
+ #: chart count
+ count = 0
+
+ # this attribute is overriden by children of this
+ # class
+ CHART_FILENAME = None
+ template_environment = Environment(lstrip_blocks=True, trim_blocks=True,
+ loader=pl)
+
+ def __init__(self, **kwargs):
+ """
+ This is the base class for all the charts. The following keywords are
+ accepted:
+ :keyword: **display_container** - default: ``True``
+ """
+ # set the model
+ self.model = self.__class__.__name__ #: The chart model,
+ self.div_name = kwargs.get("renderTo", "container")
+
+ # an Instance of Jinja2 template
+ self.template_page_highcharts = template_page
+ self.template_content_highcharts = template_content
+
+ # set Javascript src, Highcharts lib needs to make sure it's up to date
+ self.JSsource = [
+ 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
+ 'https://code.highcharts.com/stock/6/highstock.js',
+ 'https://code.highcharts.com/stock/6/modules/exporting.js',
+ 'https://code.highcharts.com/6/highcharts-more.js',
+ ]
+
+ # set CSS src
+ self.CSSsource = [
+ 'https://www.highcharts.com/highslide/highslide.css',
+
+ ]
+ # set data
+ self.data = []
+ self.data_temp = []
+
+ # set navigator series
+ self.navi_seri_flag = False
+ self.navi_seri = {}
+ self.navi_seri_temp = {}
+
+ # Data from jsonp
+ self.jsonp_data_flag = False
+ self.jsonp_data_url_list = [] # DEM 2017/04/25: List of JSON data sources
+
+ # javascript
+ self.jscript_head_flag = False
+ self.jscript_head = kwargs.get('jscript_head', None)
+ self.jscript_end_flag = False
+ self.jscript_end = kwargs.get('jscript_end', None)
+
+ # accepted keywords
+ self.div_style = kwargs.get('style', '')
+ self.date_flag = kwargs.get('date_flag', False)
+
+ # None keywords attribute that should be modified by methods
+ # We should change all these to _attr
+
+ self._htmlcontent = '' #: written by buildhtml
+ self.htmlheader = ''
+ #: Place holder for the graph (the HTML div)
+ #: Written by ``buildcontainer``
+ self.container = u''
+ #: Header for javascript code
+ self.containerheader = u''
+ # Loading message
+ self.loading = 'Loading....'
+
+ # Bind Base Classes to self
+ self.options = {
+ "chart": ChartOptions(),
+ "colors": ColorsOptions(),
+ "credits": CreditsOptions(),
+ #"data": #NotImplemented
+ "exporting": ExportingOptions(),
+ "labels": LabelsOptions(),
+ "legend": LegendOptions(),
+ "loading": LoadingOptions(),
+ "navigation": NavigationOptions(),
+ "navigator": NavigatorOptions(),
+ "plotOptions": PlotOptions(),
+ "rangeSelector": RangeSelectorOptions(),
+ "scrollbar": ScrollbarOptions(),
+ "series": SeriesData(),
+ "subtitle": SubtitleOptions(),
+ "title": TitleOptions(),
+ "tooltip": TooltipOptions(),
+ "xAxis": xAxisOptions(),
+ "yAxis": yAxisOptions(),
+ }
+
+ self.setOptions = {
+ "global": GlobalOptions(),
+ "lang": LangOptions(),
+ }
+
+ self.__load_defaults__()
+
+ # Process kwargs
+ allowed_kwargs = [
+ "width",
+ "height",
+ "renderTo",
+ "backgroundColor",
+ "events",
+ "marginBottom",
+ "marginTop",
+ "marginRight",
+ "marginLeft"
+ ]
+
+ for keyword in allowed_kwargs:
+ if keyword in kwargs:
+ self.options['chart'].update_dict(**{keyword:kwargs[keyword]})
+ # Some Extra Vals to store:
+ self.data_set_count = 0
+ self.drilldown_data_set_count = 0
+
+
+ def __load_defaults__(self):
+ self.options["chart"].update_dict(renderTo='container')
+ self.options["title"].update_dict(text='A New Highchart')
+ self.options["credits"].update_dict(enabled=False)
+
+
+ def add_JSsource(self, new_src):
+ """add additional js script source(s)"""
+ if isinstance(new_src, list):
+ for h in new_src:
+ self.JSsource.append(h)
+ elif isinstance(new_src, basestring):
+ self.JSsource.append(new_src)
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src))
+
+
+ def add_CSSsource(self, new_src):
+ """add additional css source(s)"""
+ if isinstance(new_src, list):
+ for h in new_src:
+ self.CSSsource.append(h)
+ elif isinstance(new_src, basestring):
+ self.CSSsource.append(new_src)
+ else:
+ raise OptionTypeError("Option: %s Not Allowed For Series Type: %s" % type(new_src))
+
+
+ def add_data_set(self, data, series_type="line", name=None, **kwargs):
+ """set data for series option in highstocks"""
+
+ self.data_set_count += 1
+ if not name:
+ name = "Series %d" % self.data_set_count
+ kwargs.update({'name':name})
+
+ series_data = Series(data, series_type=series_type, **kwargs)
+ series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__())
+ self.data_temp.append(series_data)
+
+
+ def add_data_from_jsonp(self, data_src, data_name='json_data', series_type="line", name=None, **kwargs):
+ """set map data directly from a https source
+ the data_src is the https link for data
+ and it must be in jsonp format
+ """
+ if not self.jsonp_data_flag:
+ self.jsonp_data_flag = True
+
+ if data_name == 'data':
+ data_name = 'json_'+ data_name
+
+ self.jsonp_data = data_name
+ self.add_data_set(RawJavaScriptText(self.jsonp_data), series_type, name=name, **kwargs)
+ # DEM 2017/04/25: Append new JSON data source to a list instead of
+ # replacing whatever already exists
+ self.jsonp_data_url_list.append(json.dumps(data_src))
+
+
+ def add_navi_series(self, data, series_type="line", **kwargs):
+ """set series for navigator option in highstocks"""
+
+ self.navi_seri_flag = True
+ series_data = Series(data, series_type=series_type, **kwargs)
+ series_data.__options__().update(SeriesOptions(series_type=series_type, **kwargs).__options__())
+ self.navi_seri_temp = series_data
+
+ def add_navi_series_from_jsonp(self, data_src=None, data_name='json_data', series_type="line", **kwargs):
+ """set series for navigator option in highstocks"""
+
+ if not self.jsonp_data_flag:
+ self.jsonp_data_flag = True
+ self.jsonp_data_url = json.dumps(data_src)
+
+ if data_name == 'data':
+ data_name = 'json_'+ data_name
+
+ self.jsonp_data = data_name
+
+ self.add_navi_series(RawJavaScriptText(self.jsonp_data), series_type, **kwargs)
+
+
+ def add_JSscript(self, js_script, js_loc):
+ """add (highcharts) javascript in the beginning or at the end of script
+ use only if necessary
+ """
+ if js_loc == 'head':
+ self.jscript_head_flag = True
+ if self.jscript_head:
+ self.jscript_head = self.jscript_head + '\n' + js_script
+ else:
+ self.jscript_head = js_script
+ elif js_loc == 'end':
+ self.jscript_end_flag = True
+ if self.jscript_end:
+ self.jscript_end = self.jscript_end + '\n' + js_script
+ else:
+ self.jscript_end = js_script
+ else:
+ raise OptionTypeError("Not An Accepted script location: %s, either 'head' or 'end'"
+ % js_loc)
+
+
+ def set_options(self, option_type, option_dict, force_options=False):
+ """set plot options """
+ if force_options:
+ self.options[option_type].update(option_dict)
+ elif (option_type == 'yAxis' or option_type == 'xAxis') and isinstance(option_dict, list):
+ # For multi-Axis
+ self.options[option_type] = MultiAxis(option_type)
+ for each_dict in option_dict:
+ self.options[option_type].update(**each_dict)
+ elif option_type == 'colors':
+ self.options["colors"].set_colors(option_dict) # option_dict should be a list
+ elif option_type in ["global" , "lang"]: #Highcharts.setOptions:
+ self.setOptions[option_type].update_dict(**option_dict)
+ else:
+ self.options[option_type].update_dict(**option_dict)
+
+
+ def set_dict_options(self, options):
+ """for dictionary-like inputs (as object in Javascript)
+ options must be in python dictionary format
+ """
+ if isinstance(options, dict):
+ for key, option_data in options.items():
+ self.set_options(key, option_data)
+ else:
+ raise OptionTypeError("Not An Accepted Input Format: %s. Must be Dictionary" %type(options))
+
+
+ def buildcontent(self):
+ """build HTML content only, no header or body tags"""
+
+ self.buildcontainer()
+ self.option = json.dumps(self.options, cls = HighchartsEncoder)
+ self.setoption = json.dumps(self.setOptions, cls = HighchartsEncoder)
+ self.data = json.dumps(self.data_temp, cls = HighchartsEncoder)
+
+ # DEM 2017/04/25: Make 'data' available as an array
+ # ... this permits jinja2 array access to each data definition
+ # ... which is useful for looping over multiple data sources
+ self.data_list = [json.dumps(x, cls = HighchartsEncoder) for x in self.data_temp]
+
+ if self.navi_seri_flag:
+ self.navi_seri = json.dumps(self.navi_seri_temp, cls = HighchartsEncoder)
+
+ self._htmlcontent = self.template_content_highcharts.render(chart=self).encode('utf-8')
+
+
+ def buildhtml(self):
+ """build the HTML page
+ create the htmlheader with css / js
+ create html page
+ """
+ self.buildcontent()
+ self.buildhtmlheader()
+ self.content = self._htmlcontent.decode('utf-8') # need to ensure unicode
+ self._htmlcontent = self.template_page_highcharts.render(chart=self)
+ return self._htmlcontent
+
+
+ def buildhtmlheader(self):
+ """generate HTML header content"""
+
+ self.header_css = [
+ '' % h for h in self.CSSsource
+ ]
+
+ self.header_js = [
+ '' % h for h in self.JSsource
+ ]
+
+ self.htmlheader = ''
+ for css in self.header_css:
+ self.htmlheader += css
+ for js in self.header_js:
+ self.htmlheader += js
+
+
+ def buildcontainer(self):
+ """generate HTML div"""
+ if self.container:
+ return
+ # Create HTML div with style
+ if self.options['chart'].width:
+ if str(self.options['chart'].width)[-1] != '%':
+ self.div_style += 'width:%spx;' % self.options['chart'].width
+ else:
+ self.div_style += 'width:%s;' % self.options['chart'].width
+ if self.options['chart'].height:
+ if str(self.options['chart'].height)[-1] != '%':
+ self.div_style += 'height:%spx;' % self.options['chart'].height
+ else:
+ self.div_style += 'height:%s;' % self.options['chart'].height
+
+ self.div_name = self.options['chart'].__dict__['renderTo'] # recheck div name
+ self.container = self.containerheader + \
+ '%s
\n' % (self.div_name, self.div_style, self.loading)
+
+ @property
+ def htmlcontent(self):
+ return self.buildhtml()
+
+ @property
+ def iframe(self):
+ htmlsrcdoc = html.escape(self.htmlcontent)
+ htmlsrcdoc = re.sub('\\n', ' ', htmlsrcdoc)
+ htmlsrcdoc = re.sub(' +', ' ', htmlsrcdoc)
+ width = int(self.options['chart'].__dict__['width']) if self.options['chart'].__dict__.get('width') else 820
+ height = int(self.options['chart'].__dict__['height']) if self.options['chart'].__dict__.get('height') else 520
+
+ if self.options['chart'].__dict__.get('options3d'):
+ if len(htmlsrcdoc) < 99965000 :
+ return ''
+ else:
+ return ''
+ else:
+ return ''
+
+ def __str__(self):
+ """return htmlcontent"""
+ #self.buildhtml()
+ return self.htmlcontent
+
+ def save_file(self, filename = 'StockChart'):
+ """ save htmlcontent as .html file """
+ filename = filename + '.html'
+
+ with open(filename, 'w') as f:
+ #self.buildhtml()
+ f.write(self.htmlcontent)
+
+ f.closed
+
+class HighchartsEncoder(json.JSONEncoder):
+ def __init__(self, *args, **kwargs):
+ json.JSONEncoder.__init__(self, *args, **kwargs)
+ self._replacement_map = {}
+
+ def default(self, obj):
+ if isinstance(obj, RawJavaScriptText):
+ key = uuid.uuid4().hex
+ self._replacement_map[key] = obj.get_jstext()
+ return key
+ elif isinstance(obj, datetime.datetime):
+ utc = obj.utctimetuple()
+ obj = (u"Date.UTC({year},{month},{day},{hours},{minutes},{seconds},{millisec})"
+ .format(year=utc[0], month=utc[1]-1, day=utc[2], hours=utc[3],
+ minutes=utc[4], seconds=utc[5], millisec=obj.microsecond/1000))
+ return RawJavaScriptText(obj)
+ elif isinstance(obj, BaseOptions) or isinstance(obj, MultiAxis):
+ return obj.__jsonable__()
+ elif isinstance(obj, CSSObject) or isinstance(obj, Formatter) or isinstance(obj, JSfunction):
+ return obj.__jsonable__()
+ elif isinstance(obj, SeriesOptions) or isinstance(obj, Series):
+ return obj.__jsonable__()
+ elif isinstance(obj, CommonObject) or isinstance(obj, ArrayObject) or isinstance(obj, ColorObject):
+ return obj.__jsonable__()
+ else:
+ return json.JSONEncoder.default(self, obj)
+
+ def encode(self, obj):
+ result = json.JSONEncoder.encode(self, obj)
+ for k, v in self._replacement_map.items():
+ result = result.replace('"%s"' % (k,), v)
+ return result
+
+
+class OptionTypeError(Exception):
+
+ def __init__(self,*args):
+ self.args = args
diff --git a/build/lib/highcharts/highstock/highstock_helper.py b/build/lib/highcharts/highstock/highstock_helper.py
new file mode 100644
index 0000000..029d885
--- /dev/null
+++ b/build/lib/highcharts/highstock/highstock_helper.py
@@ -0,0 +1,153 @@
+# -*- coding: utf-8 -*-
+from future.standard_library import install_aliases
+install_aliases()
+from past.builtins import basestring
+
+from urllib.request import urlopen
+import urllib
+
+import json, os, sys
+import datetime, re
+from datetime import tzinfo
+
+
+def jsonp_loader(url, prefix_regex=r'^(.*\()', suffix_regex=r'(\);)$', sub_d=None, sub_by=''):
+ """jsonp_loader is to request (JSON) data from a server in a different domain (JSONP)
+ and covert to python readable data.
+ 1. url is the url (https) where data is located
+ 2. "prefix_regex" and "suffix_regex" are regex patterns used to
+ remove JSONP specific prefix and suffix, such as callback header: "callback(" and end: ");",
+ 3. "sub_d" is regex patterns for any unwanted string in loaded json data (will be replaced by sub_by).
+ 4. "sub_by" is the string to replace any unwanted string defined by sub_d
+ For function coverstion, such as Data.UTC to datetime.datetime, please check JSONPDecoder
+ """
+
+ hdr = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7'}
+ req = urllib.request.Request(url, headers=hdr)
+ page = urlopen(req)
+ result = page.read().decode("utf-8")
+ # replace all the redundant info with sub_by
+ if sub_d:
+ result = re.sub(sub_d, sub_by, result)
+
+ prefix = re.search(prefix_regex, result).group()
+ suffix = re.search(suffix_regex, result).group()
+ if result.startswith(prefix) and result.endswith(suffix):
+ result = result[len(prefix):-len(suffix)]
+ return json.loads(result, encoding='utf8', cls=JSONPDecoder)
+
+def interpolateRGB(lowRGB, highRGB, fraction):
+ color = []
+
+ for i in range(3):
+ color.append((highRGB[i] - lowRGB[i]) * fraction + lowRGB[i])
+
+ return 'rgb(' + str(int(round(color[0],0))) + ',' + str(int(round(color[1],0))) + ',' + \
+ str(int(round(color[2],0))) + ')'
+
+
+class JSONPDecoder(json.JSONDecoder):
+ """Customized JSON decoder. It is used to convert everything
+ that is python non-compatible (usually Javascript functions)
+ to one that can be read by python. It needs to coordinate with
+ customized JSON encoder in main library, such as highcharts.py,
+ to convert back to Javascript-compatiable functions.
+ For example: in _iterdecode, it checks if queried JSON has Data.UTC
+ and (if yes)converts it to datetime.datetime
+ """
+
+ def decode(self, json_string):
+ """
+ json_string is basicly string that you give to json.loads method
+ """
+
+ default_obj = super(JSONPDecoder, self).decode(json_string)
+
+ return list(self._iterdecode(default_obj))[0]
+
+ def _iterdecode_list(self, lst):
+ new_lst = []
+ for item in lst:
+ for chunk in self._iterdecode(item):
+ new_lst.append(chunk)
+ yield new_lst
+
+ def _iterdecode_dict(self, dct):
+ new_dct = {}
+ for key, value in dct.items():
+ for chunk in self._iterdecode(value):
+ new_dct[key] = chunk
+ yield new_dct
+
+ def _iterdecode(self, obj):
+ if isinstance(obj, (list, tuple)):
+ for chunk in self._iterdecode_list(obj):
+ yield chunk
+
+ elif isinstance(obj, dict):
+ for chunk in self._iterdecode_dict(obj):
+ yield chunk
+
+ elif isinstance(obj, basestring) and JSONPDecoder.is_js_date_utc(obj):
+ m = JSONPDecoder.is_js_date_utc(obj)
+ yield JSONPDecoder.json2datetime(m)
+
+ else:
+ yield obj
+
+ @staticmethod
+ def is_js_date_utc(json):
+ """Check if the string contains Date.UTC function
+ and return match group(s) if there is
+ """
+
+ JS_date_utc_pattern = r'Date\.UTC\(([0-9]+,[0-9]+,[0-9]+)(,[0-9]+,[0-9]+,[0-9]+)?(,[0-9]+)?\)'
+ re_date = re.compile(JS_date_utc_pattern, re.M)
+
+ if re_date.search(json):
+ return re_date.search(json).group(0)
+ else:
+ return False
+
+ @staticmethod
+ def json2datetime(json):
+ """Convert JSON representation to date or datetime object depending on
+ the argument count. Requires UTC datetime representation.
+ Raises ValueError if the string cannot be parsed.
+ """
+
+ json_m = re.search(r'([0-9]+,[0-9]+,[0-9]+)(,[0-9]+,[0-9]+,[0-9]+)?(,[0-9]+)?', json)
+ args=json_m.group(0).split(',')
+
+ try:
+ args = list(map(int, args))
+ except ValueError:
+ raise ValueError('Invalid arguments: %s'%json)
+
+ if len(args)==3:
+ return datetime.datetime(args[0], args[1]+1, args[2])
+ elif len(args)==6:
+ return datetime.datetime(args[0], args[1]+1, args[2],
+ args[3], args[4], args[5], tzinfo=UTC())
+ elif len(args)==7:
+ args[6]*=1000
+ return datetime.datetime(args[0], args[1]+1, args[2],
+ args[3], args[4], args[5], args[6], tzinfo=UTC())
+ raise ValueError('Invalid number of arguments: %s'%json)
+
+
+class UTC(tzinfo):
+ """UTC"""
+
+ ZERO=datetime.timedelta(0)
+
+ def utcoffset(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return "UTC"
+
+ def dst(self, dt):
+ return ZERO
+
+
diff --git a/build/lib/highcharts/highstock/highstock_types.py b/build/lib/highcharts/highstock/highstock_types.py
new file mode 100644
index 0000000..83e76c6
--- /dev/null
+++ b/build/lib/highcharts/highstock/highstock_types.py
@@ -0,0 +1,559 @@
+# -*- coding: UTF-8 -*-
+from past.builtins import basestring
+
+import json, datetime
+from .common import Formatter, Events, Position, ContextButton, Options3d, ResetZoomButton, DataGrouping, \
+ Labels, Marker, Point, PlotBands, States, Tooltip, Title, Zones, Levels, Shadow, \
+ JSfunction, ColorObject, CSSObject, SVGObject, \
+ CommonObject, ArrayObject
+
+PLOT_OPTION_ALLOWED_ARGS = {
+ "common": {
+ "allowPointSelect": bool,
+ "animation": bool,
+ "color": (ColorObject, basestring, dict),
+ "cursor": basestring,
+ "dataGrouping": (DataGrouping, dict),
+ "dataLabels": (Labels, dict),
+ "enableMouseTracking": bool,
+ "events": (Events, dict),
+ "id": basestring,
+ "index": [float, int],
+ "name": basestring,
+ "point": (Point, dict),
+ "selected": bool,
+ "showCheckbox": bool,
+ "showInLegend": bool,
+ "states": (States, dict),
+ "stickyTracking": bool,
+ "tooltip": (Tooltip, dict),
+ "visible": bool,
+ "xAxis": [int, basestring],
+ "yAxis": [int, basestring],
+ "zIndex": int,
+ "zoneAxis": basestring,
+ "zones": (Zones, dict),
+ },
+ "area": {
+ "compare": basestring,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "gapSize": [int, float],
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": (int,basestring, datetime.datetime),
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "step": bool,
+ "threshold": [int, type(None)],
+ "trackByArea": bool,
+ "turboThreshold": int,
+ },
+ "arearange": {
+ "compare": basestring,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "gapSize": [int, float],
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "trackByArea": bool,
+ "turboThreshold": int,
+ },
+ "areaspline": {
+ "cropThreshold": int,
+ "compare": basestring,
+ "connectNulls": bool,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "gapSize": [int, float],
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "threshold": [int, type(None)],
+ "turboThreshold": int,
+ "trackByArea": bool,
+ },
+ "areasplinerange": {
+ "cropThreshold": int,
+ "compare": basestring,
+ "connectNulls": bool,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "gapSize": [int, float],
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "threshold": [int, type(None)],
+ "turboThreshold": int,
+ "trackByArea": bool,
+ },
+ "candlestick": {
+ "colors": list,
+ "cropThreshold": int,
+ "connectNulls": bool,
+ "dashStyle": basestring,
+ "fillColor": (ColorObject, basestring, dict),
+ "fillOpacity": float,
+ "groupPadding": [int, float],
+ "grouping": bool,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "minPointLength": [int, float],
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointRange": [int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "pointWidth": [int, float],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "upColor": (ColorObject, basestring, dict),
+ "upLineColor": (ColorObject, basestring, dict),
+ "turboThreshold": int,
+ "trackByArea": bool,
+ },
+ "column": {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": [int, basestring],
+ "colorByPoint": bool,
+ "colors": list,
+ "compare": basestring,
+ "cropThreshold": int,
+ "groupPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "linkedTo": basestring,
+ "minPointLength": int,
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPadding": [float, int],
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "pointWidth": [int, float],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "columnrange": {
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": [int, basestring],
+ "colorByPoint": bool,
+ "colors": list,
+ "compare": basestring,
+ "cropThreshold": int,
+ "groupPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "linkedTo": basestring,
+ "minPointLength": int,
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPadding": [float, int],
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "pointWidth": [int, float],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "flags": {
+ "colors": list,
+ "cropThreshold": int,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "onSeries": basestring,
+ "pointIntervalUnit": basestring,
+ "shadow": [bool, dict],
+ "shape": basestring,
+ "stack": basestring,
+ "stackDistance": [int, float],
+ "style": (CSSObject, dict),
+ "y": [int, float],
+ "useHTML": bool,
+ },
+ "line": {
+ "compare": basestring,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "gapSize": [int, float],
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linecap": basestring,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "step": basestring,
+ "turboThreshold": int,
+ },
+ "ohlc": {
+ "colorByPoint": bool,
+ "colors": list,
+ "compare": basestring,
+ "cropThreshold": int,
+ "groupPadding": [float, int],
+ "grouping": bool,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "minPointLength": int,
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPadding": [float, int],
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "pointWidth": [int, float],
+ "shadow": [bool, dict],
+ "stack": basestring,
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "polygon": {
+ "compare": basestring,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "scatter": {
+ "compare": basestring,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "negativeColor": (ColorObject, basestring, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "series": {
+ "compare": basestring,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "gapSize": [int, float],
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+ "spline": {
+ "compare": basestring,
+ "connectNulls": bool,
+ "cropThreshold": int,
+ "dashStyle": basestring,
+ "gapSize": [int, float],
+ "keys": list,
+ "legendIndex": [int, float],
+ "lineWidth": int,
+ "linkedTo": basestring,
+ "marker": (Marker, dict),
+ "pointInterval": int,
+ "pointIntervalUnit": basestring,
+ "pointPlacement": [basestring, int, float],
+ "pointRange": int,
+ "pointStart": [int,basestring,datetime.datetime],
+ "shadow": [bool, dict],
+ "stacking": basestring,
+ "turboThreshold": int,
+ },
+}
+
+DATA_SERIES_ALLOWED_OPTIONS = {
+ "color": (ColorObject, basestring, dict),
+ "connectEnds": bool,
+ "connectNulls": bool,
+ "dataLabels": (Labels, dict),
+ "dataParser": NotImplemented,
+ "dataURL": NotImplemented,
+ "drilldown": basestring,
+ "events": (Events, dict),
+ "high": [int, float],
+ "id": basestring,
+ "index": int,
+ "legendIndex": int,
+ "name": basestring,
+ "marker": (Marker, dict),
+ "selected": bool,
+ "sliced": bool,
+ "showInLegend": bool,
+ "type": basestring,
+ "visible": bool,
+ "x": [int, float, datetime.datetime],
+ "xAxis": int,
+ "yAxis": int,
+}
+
+DEFAULT_OPTIONS = {
+
+}
+
+class OptionTypeError(Exception):
+
+ def __init__(self,*args):
+ self.args = args
+
+
+class SeriesOptions(object):
+ """Class for plotOptions"""
+
+ def __init__(self,series_type="line",supress_errors=False,**kwargs):
+ self.load_defaults(series_type)
+ self.process_kwargs(kwargs,series_type=series_type,supress_errors=supress_errors)
+
+ @staticmethod
+ def __validate_options__(k,v,ov):
+ if isinstance(ov,list):
+ if isinstance(v,tuple(ov)): return True
+ else:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ else:
+ if ov == NotImplemented: raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,ov): return True
+ else: return False
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def update(self,series_type, **kwargs):
+ allowed_args = PLOT_OPTION_ALLOWED_ARGS[series_type]
+ allowed_args.update(PLOT_OPTION_ALLOWED_ARGS["common"])
+ for k, v in kwargs.items():
+ if k in allowed_args:
+ if SeriesOptions.__validate_options__(k,v,allowed_args[k]):
+ if isinstance(allowed_args[k], tuple) and isinstance(allowed_args[k][0](), CommonObject):
+ # re-construct input dict with existing options in objects
+ if self.__getattr__(k):
+ if isinstance(v, dict):
+ self.__options__()[k].update(v)
+ else:
+ self.__options__()[k].__options__().update(v)
+ else:
+ self.__options__().update({k:allowed_args[k][0](**v)})
+
+ elif isinstance(allowed_args[k], tuple) and isinstance(allowed_args[k][0](), ArrayObject):
+ # update array
+ if isinstance(v, dict):
+ self.__dict__[k].append(allowed_args[k][0](**v))
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].append(allowed_args[k][0](**item))
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(v))
+
+ elif isinstance(allowed_args[k], tuple) and \
+ (isinstance(allowed_args[k][0](), CSSObject) or isinstance(allowed_args[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items():
+ self.__dict__[k].__options__().update({key:value})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+
+ elif isinstance(allowed_args[k], tuple) and (isinstance(allowed_args[k][0](), JSfunction) or
+ isinstance(allowed_args[k][0](), Formatter) or isinstance(allowed_args[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ print(k,v)
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % allowed_args[k])
+
+
+ def process_kwargs(self,kwargs,series_type,supress_errors=False):
+ allowed_args = PLOT_OPTION_ALLOWED_ARGS[series_type]
+ allowed_args.update(PLOT_OPTION_ALLOWED_ARGS["common"])
+
+ for k, v in kwargs.items():
+ if k in allowed_args:
+ if SeriesOptions.__validate_options__(k,v,allowed_args[k]):
+ if isinstance(allowed_args[k], tuple):
+ if isinstance(v, dict):
+ self.__dict__.update({k:allowed_args[k][0](**v)})
+ elif isinstance(v, list):
+ if len(v) == 1:
+ self.__dict__.update({k:allowed_args[k][0](**v[0])})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](**v[0])})
+ for item in v[1:]:
+ self.__dict__[k].update(item)
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:allowed_args[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ print(k,v)
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % allowed_args[k])
+
+
+ def load_defaults(self,series_type): # not in use
+ self.process_kwargs(DEFAULT_OPTIONS.get(series_type,{}),series_type)
+
+ def __getattr__(self,item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class Series(object):
+ """Series class for input data """
+
+ def __init__(self,data,series_type="line",supress_errors=False,**kwargs):
+
+ # List of dictionaries. Each dict contains data and properties,
+ # which need to handle before construct the object for series
+ if isinstance(data, list):
+ for item in data:
+ if isinstance(item, dict):
+ for k, v in item.items():
+ if k in DATA_SERIES_ALLOWED_OPTIONS:
+ if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
+ if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
+ if isinstance(v, dict):
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, datetime.datetime):
+ item.update({k:v})
+ else:
+ item.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
+ else:
+ item.update({k:v})
+
+ self.__dict__.update({
+ "data": data,
+ "type": series_type,
+ })
+
+ # Series propertie can be input as kwargs, which is handled here
+ for k, v in kwargs.items():
+ if k in DATA_SERIES_ALLOWED_OPTIONS:
+ if SeriesOptions.__validate_options__(k,v,DATA_SERIES_ALLOWED_OPTIONS[k]):
+ if isinstance(DATA_SERIES_ALLOWED_OPTIONS[k], tuple):
+ if isinstance(v, dict):
+ self.__dict__.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, CommonObject) or isinstance(v, ArrayObject) or \
+ isinstance(v, CSSObject) or isinstance(v, SVGObject) or isinstance(v, ColorObject) or \
+ isinstance(v, JSfunction) or isinstance(v, Formatter) or isinstance(v, datetime.datetime):
+ self.__dict__.update({k:v})
+ else:
+ self.__dict__.update({k:DATA_SERIES_ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+ else:
+ if not supress_errors: raise OptionTypeError("Option Type Mismatch: Expected: %s" % DATA_SERIES_ALLOWED_OPTIONS[k])
+
+
+ def __options__(self):
+ return self.__dict__
+
+ def __jsonable__(self):
+ return self.__dict__
diff --git a/build/lib/highcharts/highstock/options.py b/build/lib/highcharts/highstock/options.py
new file mode 100644
index 0000000..4a21318
--- /dev/null
+++ b/build/lib/highcharts/highstock/options.py
@@ -0,0 +1,587 @@
+# -*- coding: UTF-8 -*-
+from past.builtins import basestring
+
+from .highstock_types import OptionTypeError, Series, SeriesOptions
+from .common import Formatter, Events, Position, ContextButton, Options3d, ResetZoomButton, \
+ Labels, PlotBands, PlotLines, Title, Items, Navigation, Handles, Background, Breaks, \
+ DateTimeLabelFormats, Zones, Levels, Buttons, \
+ JSfunction, ColorObject, CSSObject, SVGObject, CommonObject, ArrayObject
+
+import json, datetime
+
+# Base Option Class
+class BaseOptions(object):
+
+ def __init__(self,**kwargs):
+ self.update_dict(**kwargs)
+
+ def __display_options__(self):
+ print(json.dumps(self.__dict__, indent=4, sort_keys=True))
+
+ def __jsonable__(self):
+ return self.__dict__
+
+ def __validate_options__(self, k, v, ov):
+ if ov == NotImplemented:
+ raise OptionTypeError("Option Type Currently Not Supported: %s" % k)
+ if isinstance(v,dict) and isinstance(ov,dict):
+ keys = v.keys()
+ if len(keys) > 1:
+ raise NotImplementedError
+ return isinstance(v[keys[0]],ov[keys[0]])
+ return isinstance(v, ov)
+
+ def update_dict(self, **kwargs):
+ for k, v in kwargs.items():
+ if k in self.ALLOWED_OPTIONS:
+ #if isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), SeriesOptions):
+ if k in PlotOptions.ALLOWED_OPTIONS.keys():
+ if self.__getattr__(k):
+ self.__dict__[k].update(series_type=k, **v)
+ else:
+ v = SeriesOptions(series_type=k, **v)
+ self.__dict__.update({k:v})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), CommonObject):
+ if isinstance(v, dict):
+ if self.__getattr__(k):
+ self.__dict__[k].update(v) #update dict
+ else: # first
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be dictionary" % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and isinstance(self.ALLOWED_OPTIONS[k][0](), ArrayObject):
+ if self.__getattr__(k): #existing attr
+ if isinstance(v, dict):
+ self.__dict__[k].update(v) # update array
+ elif isinstance(v, list):
+ for item in v:
+ self.__dict__[k].update(item) # update array
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be list or dictionary"
+ % type(v))
+ else: #first
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ elif isinstance(v, list):
+ if len(v) == 1:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v[0])})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v[0])})
+ for item in v[1:]:
+ self.__dict__[k].update(item)
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s, must be list or dictionary"
+ % type(v))
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and \
+ (isinstance(self.ALLOWED_OPTIONS[k][0](), CSSObject) or isinstance(self.ALLOWED_OPTIONS[k][0](), SVGObject)):
+ if self.__getattr__(k):
+ for key, value in v.items(): # check if v has object input
+ self.__dict__[k].__options__().update({key:value})
+
+ v = self.__dict__[k].__options__()
+ # upating object
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+
+ elif isinstance(self.ALLOWED_OPTIONS[k], tuple) and (isinstance(self.ALLOWED_OPTIONS[k][0](), JSfunction) or \
+ isinstance(self.ALLOWED_OPTIONS[k][0](), Formatter) or isinstance(self.ALLOWED_OPTIONS[k][0](), ColorObject)):
+ if isinstance(v, dict):
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](**v)})
+ else:
+ self.__dict__.update({k:self.ALLOWED_OPTIONS[k][0](v)})
+ else:
+ self.__dict__.update({k:v})
+
+ else:
+ print(self.ALLOWED_OPTIONS)
+ print(k, v)
+ raise OptionTypeError("Not An Accepted Option Type: %s" % k)
+
+
+ def __getattr__(self, item):
+ if not item in self.__dict__:
+ return None # Attribute Not Set
+ else:
+ return True
+
+
+class ChartOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "alignTicks": bool,
+ "animation": [bool, dict, basestring],
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": int,
+ "className": basestring,
+ "defaultSeriesType": basestring,
+ "events": (Events, dict),
+ "height": [int,basestring],
+ "ignoreHiddenSeries": bool,
+ "inverted": bool,
+ "margin": list,
+ "marginBottom": int,
+ "marginLeft": int,
+ "marginRight": int,
+ "marginTop": int,
+ "options3d": (Options3d, dict),
+ "plotBackgroundColor": (ColorObject, basestring, dict),
+ "plotBackgroundImage": basestring,
+ "plotBorderColor": (ColorObject, basestring, dict),
+ "plotBorderWidth": int,
+ "plotShadow": bool,
+ "polar": bool,
+ "reflow": bool,
+ "renderTo": basestring,
+ "resetZoomButton": (ResetZoomButton, dict),
+ "selectionMarkerFill": basestring,
+ "shadow": bool,
+ "showAxes": bool,
+ "spacingBottom": int,
+ "spacingLeft": int,
+ "spacingRight": int,
+ "spacingTop": int,
+ "style": (CSSObject, dict),
+ "type": basestring,
+ "width": [int,basestring],
+ "zoomType": basestring,
+ }
+
+
+class ColorsOptions(BaseOptions):
+ """ Special Case, this is simply just an array of colours """
+ def __init__(self):
+ self.colors = {}
+
+ def set_colors(self, colors):
+ if isinstance(colors, basestring):
+ self.colors = ColorObject(colors)
+ elif isinstance(colors, list) or isinstance(colors, dict):
+ self.colors = colors
+ else:
+ OptionTypeError("Not An Accepted Input Type: %s" % type(colors))
+
+ def __jsonable__(self):
+ return self.colors
+
+
+class CreditsOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "enabled": bool,
+ "href": basestring,
+ "position": (Position, dict),
+ "style": (CSSObject, dict),
+ "text": basestring,
+ }
+
+
+class ExportingOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "buttons": (ContextButton, dict),
+ "chartOptions": (ChartOptions, dict),
+ "enabled": bool,
+ "filename": basestring,
+ "formAttributes": NotImplemented,
+ "scale": int,
+ "sourceHeight": int,
+ "sourceWidth": int,
+ "type": basestring,
+ "url": basestring,
+ "width": int,
+ }
+
+
+class GlobalOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "Date": NotImplemented,
+ "VMLRadialGradientURL": basestring,
+ "canvasToolsURL": basestring,
+ "getTimezoneOffset": (JSfunction, basestring),
+ "timezoneOffset": int,
+ "useUTC": bool,
+ }
+
+
+class LabelsOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "items": (Items, dict),
+ "style": (CSSObject, dict),
+ }
+
+
+class LangOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "decimalPoint": basestring,
+ "downloadJPEG": basestring,
+ "downloadPDF": basestring,
+ "downloadPNG": basestring,
+ "donwloadSVG": basestring,
+ "exportButtonTitle": basestring,
+ "loading": basestring,
+ "months": list,
+ "noData": basestring,
+ "numericSymbols": list,
+ "printButtonTitle": basestring,
+ "resetZoom": basestring,
+ "resetZoomTitle": basestring,
+ "shortMonths": list,
+ "thousandsSep": basestring,
+ "weekdays": list,
+ }
+
+
+class LegendOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": int,
+ "enabled": bool,
+ "floating": bool,
+ "itemDistance": int,
+ "itemHiddenStyle": (CSSObject, dict),
+ "itemHoverStyle": (CSSObject, dict),
+ "itemMarginBottom": int,
+ "itemMarginTop": int,
+ "itemStyle": (CSSObject, dict),
+ "itemWidth": int,
+ "labelFormat": basestring,
+ "labelFormatter": (Formatter, JSfunction),
+ "layout": basestring,
+ "lineHeight": int,
+ "margin": int,
+ "maxHeight": int,
+ "navigation": (Navigation, dict),
+ "padding": int,
+ "reversed": bool,
+ "rtl": bool,
+ "shadow": bool,
+ "style": (CSSObject, dict),
+ "symbolHeight": int,
+ "symbolPadding": int,
+ "symbolRadius": int,
+ "symbolWidth": int,
+ "title": (Title, dict),
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "width": int,
+ "x": int,
+ "y": int,
+ }
+
+
+class LoadingOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "hideDuration": int,
+ "labelStyle": (CSSObject, dict),
+ "showDuration": int,
+ "style": (CSSObject, dict),
+ }
+
+
+class NavigationOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "buttonOptions": (ContextButton, dict),
+ "menuItemHoverStyle": (CSSObject, dict),
+ "menuItemStyle": (CSSObject, dict),
+ "menuStyle": (CSSObject, dict),
+ }
+
+
+class PlotOptions(BaseOptions):
+ """ Another Special Case: Interface With all the different Highchart Plot Types Here """
+ ALLOWED_OPTIONS = {
+ "area": (SeriesOptions, dict),
+ "arearange": (SeriesOptions, dict),
+ "areaspline": (SeriesOptions, dict),
+ "areasplinerange": (SeriesOptions, dict),
+ "candlestick": (SeriesOptions, dict),
+ "column": (SeriesOptions, dict),
+ "columnrange": (SeriesOptions, dict),
+ "flags": (SeriesOptions, dict),
+ "line": (SeriesOptions, dict),
+ "ohlc": (SeriesOptions, dict),
+ "polygon": (SeriesOptions, dict),
+ "scatter": (SeriesOptions, dict),
+ "series": (SeriesOptions, dict),
+ "spline": (SeriesOptions, dict),
+ }
+
+class RangeSelectorOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "allButtonsEnabled": bool,
+ "buttonSpacing": [int, float],
+ "buttonTheme": (SVGObject, dict),
+ "buttons": (Buttons, list),
+ "enabled": bool,
+ "inputBoxBorderColor": (ColorObject, basestring, dict),
+ "inputBoxHeight": [int, float],
+ "inputBoxWidth": [int, float],
+ "inputDateFormat": basestring,
+ "inputDateParser": (JSfunction, basestring),
+ "inputEditDateFormat": basestring,
+ "inputEnabled": bool,
+ "inputPosition": (Position, dict),
+ "inputStyle": (CSSObject, dict),
+ "labelStyle": (CSSObject, dict),
+ "selected": [int, float],
+ }
+
+class ScrollbarOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "barBackgroundColor": (ColorObject, basestring, dict),
+ "barBorderColor": (ColorObject, basestring, dict),
+ "barBorderRadius": [int, float],
+ "barBorderWidth": [int, float],
+ "buttonArrowColor": (ColorObject, basestring, dict),
+ "buttonBackgroundColor": (ColorObject, basestring, dict),
+ "buttonBorderColor": (ColorObject, basestring, dict),
+ "buttonBorderRadius": [int, float],
+ "buttonBorderWidth": [int, float],
+ "enabled": bool,
+ "height": [int, float],
+ "liveRedraw": bool,
+ "minWidth": [int, float],
+ "rifleColor": (ColorObject, basestring, dict),
+ "trackBackgroundColor": (ColorObject, basestring, dict),
+ "trackBorderColor": (ColorObject, basestring, dict),
+ "trackBorderRadius": [int, float],
+ "trackBorderWidth": [int, float],
+ }
+
+class SeriesData(BaseOptions):
+ """ Another Special Case: Stores Data Series in an array for returning to the chart object """
+ def __init__(self):
+ #self.__dict__.update([])
+ self = []
+
+
+class SubtitleOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "floating": bool,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+
+class TitleOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "align": basestring,
+ "floating": bool,
+ "margin": int,
+ "style": (CSSObject, dict),
+ "text": basestring,
+ "useHTML": bool,
+ "verticalAlign": basestring,
+ "x": int,
+ "y": int,
+ }
+
+
+class TooltipOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "animation": bool,
+ "backgroundColor": (ColorObject, basestring, dict),
+ "borderColor": (ColorObject, basestring, dict),
+ "borderRadius": int,
+ "borderWidth": int,
+ "crosshairs": [bool, list, dict],
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "enabled": bool,
+ "followPointer": bool,
+ "followTouchMove": bool,
+ "footerFormat": basestring,
+ "formatter": (Formatter, JSfunction),
+ "headerFormat": basestring,
+ "pointFormat": basestring,
+ "positioner": (JSfunction, basestring),
+ "shadow": bool,
+ "shared": bool,
+ "snap": int,
+ "style": (CSSObject, dict),
+ "useHTML": bool,
+ "valueDecimals": int,
+ "valuePrefix": basestring,
+ "valueSuffix": basestring,
+ "xDateFormat": basestring,
+ }
+
+
+class xAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "allowDecimals": bool,
+ "alternateGridColor": (ColorObject, basestring, dict),
+ "breaks":(Breaks, list),
+ "categories": list,
+ 'crosshair': bool,
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineWidth": int,
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": int,
+ "max": [float, int],
+ "maxPadding": [float, int],
+ "maxZoom": NotImplemented,
+ "min": [float, int],
+ "minPadding": [float, int],
+ "minRange": int,
+ "minTickInterval": int,
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "offset": bool,
+ "opposite": bool,
+ "ordinal": bool,
+ "plotBands": (PlotBands, list),
+ "plotLines": (PlotLines, list),
+ "reversed": bool,
+ "showEmpty": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": (JSfunction, basestring),
+ "tickPositions": list,
+ "tickWidth": int,
+ "tickmarkPlacement": basestring,
+ "title": (Title, dict),
+ "type": basestring,
+ "units": list
+ }
+
+
+class yAxisOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "allowDecimals": bool,
+ "alternateGridColor": (ColorObject, basestring, dict),
+ "breaks": (Breaks, list),
+ "categories": list,
+ "ceiling": (int, float),
+ "dateTimeLabelFormats": (DateTimeLabelFormats, dict),
+ "endOnTick": bool,
+ "events": (Events, dict),
+ "floor": (int, float),
+ "gridLineColor": (ColorObject, basestring, dict),
+ "gridLineDashStyle": basestring,
+ "gridLineInterpolation": basestring,
+ "gridLineWidth": int,
+ "gridZIndex": int,
+ "height": [int, float, basestring],
+ "id": basestring,
+ "labels": (Labels, dict),
+ "lineColor": (ColorObject, basestring, dict),
+ "lineWidth": int,
+ "linkedTo": int,
+ "max": [float, int],
+ "maxColor": (ColorObject, basestring, dict),
+ "maxPadding": [float, int],
+ "maxZoom": NotImplemented,
+ "min": [float, int],
+ "minColor": (ColorObject, basestring, dict),
+ "minPadding": [float, int],
+ "minRange": int,
+ "minTickInterval": int,
+ "minorGridLineColor": (ColorObject, basestring, dict),
+ "minorGridLineDashStyle": basestring,
+ "minorGridLineWidth": int,
+ "minorTickColor": (ColorObject, basestring, dict),
+ "minorTickInterval": int,
+ "minorTickLength": int,
+ "minorTickPosition": basestring,
+ "minorTickWidth": int,
+ "offset": bool,
+ "opposite": bool,
+ "ordinal": bool,
+ "plotBands": (PlotBands, list),
+ "plotLines": (PlotLines, list),
+ "reversed": bool,
+ "reversedStacks": bool,
+ "showEmpty": bool,
+ "showFirstLabel": bool,
+ "showLastLabel": bool,
+ "stackLabels": (Labels, dict),
+ "startOfWeek": int,
+ "startOnTick": bool,
+ "stops": list,
+ "tickAmount": int,
+ "tickColor": (ColorObject, basestring, dict),
+ "tickInterval": int,
+ "tickLength": int,
+ "tickPixelInterval": int,
+ "tickPosition": basestring,
+ "tickPositioner": (JSfunction, basestring),
+ "tickPositions": list,
+ "tickWidth": int,
+ "tickmarkPlacement": basestring,
+ "title": (Title, dict),
+ "top": [int, float, basestring],
+ # DEM 2017/11/16: Note that the 'type' keyword for highstock is
+ # undocumented yet appears to be supported, likely because of underlying
+ # shared code. This permits logarithmic Y-Axis scale which is
+ # frequently useful in stock charts.
+ "type": basestring,
+ "units": list
+ }
+
+
+class NavigatorOptions(BaseOptions):
+ ALLOWED_OPTIONS = {
+ "adaptToUpdatedData": bool,
+ "baseSeries": [int, basestring],
+ "enabled": bool,
+ "handles": (Handles, dict), # need handles object
+ "height": [int, float],
+ "margin": [int, float],
+ "maskFill": (ColorObject, dict),
+ "maskInside": bool,
+ "outlineColor": (ColorObject, dict),
+ "outlineWidth": [int, float],
+ "series": dict,
+ "xAxis": (xAxisOptions, dict),
+ "yAxis": (yAxisOptions, dict),
+ }
+
+
+class MultiAxis(object):
+
+ def __init__(self, axis):
+ AXIS_LIST = {
+ "xAxis": xAxisOptions,
+ "yAxis": yAxisOptions
+ }
+ self.axis = []
+ self.AxisObj = AXIS_LIST[axis]
+
+ def update(self, **kwargs):
+ self.axis.append(self.AxisObj(**kwargs))
+
+ def __jsonable__(self):
+ return self.axis
+
diff --git a/build/lib/highcharts/highstock/templates/base.html b/build/lib/highcharts/highstock/templates/base.html
new file mode 100644
index 0000000..401d656
--- /dev/null
+++ b/build/lib/highcharts/highstock/templates/base.html
@@ -0,0 +1,21 @@
+{% block container %}
+{% endblock %}
+
+{% block start_script %}
+
+{% endblock endscript %}
\ No newline at end of file
diff --git a/build/lib/highcharts/highstock/templates/content.html b/build/lib/highcharts/highstock/templates/content.html
new file mode 100644
index 0000000..54615ba
--- /dev/null
+++ b/build/lib/highcharts/highstock/templates/content.html
@@ -0,0 +1,56 @@
+{% extends "base.html" %}
+{% block container %}
+ {{ chart.container }}
+{% endblock container %}
+
+{% block body_head %}
+
+ {% if chart.jscript_head_flag %}
+ {{chart.jscript_head}}
+ {% endif %}
+
+{% endblock body_head %}
+
+{% block body_content %}
+
+ Highcharts.setOptions({{chart.setoption}});
+ var option = {{chart.option}};
+
+ {% if chart.navi_seri_flag %}
+ var navi_data = {{chart.navi_seri}}
+ option.navigator.series = navi_data;
+ {% endif %}
+
+ var chart = new Highcharts.StockChart(option);
+
+
+ {# DEM 2017/04/25: Use a list of JSONP data sources
+ {# DEM 2017/07/27: This implementation is limited and could easily be improved! #}
+ {% if chart.jsonp_data_flag %}
+ {% for data_url in chart.jsonp_data_url_list %}
+
+ $.getJSON({{data_url}}, function ({{chart.jsonp_data}})
+ {
+ chart.addSeries({{chart.data_list[loop.index0]}});
+ });
+
+ {% endfor %}
+ {% else %}
+
+ var data = {{chart.data}};
+ var dataLen = data.length;
+ for (var ix = 0; ix < dataLen; ix++) {
+ chart.addSeries(data[ix]);
+ }
+
+ {% endif %}
+
+{% endblock body_content %}
+
+{% block body_end %}
+
+ {% if chart.jscript_end_flag %}
+ {{chart.jscript_end}}
+ {% endif %}
+
+{% endblock body_end %}
diff --git a/build/lib/highcharts/highstock/templates/page.html b/build/lib/highcharts/highstock/templates/page.html
new file mode 100644
index 0000000..dd722fe
--- /dev/null
+++ b/build/lib/highcharts/highstock/templates/page.html
@@ -0,0 +1,13 @@
+
+
+
+
+ {% for header_element in chart.header_css+chart.header_js %}
+ {{ header_element }}
+ {% endfor %}
+
+
+ {{ chart.content }}
+ {{ chart.other }}
+
+
diff --git a/build/lib/highcharts/highstock/templates/test.html b/build/lib/highcharts/highstock/templates/test.html
new file mode 100644
index 0000000..63eecc5
--- /dev/null
+++ b/build/lib/highcharts/highstock/templates/test.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ {{ chart.title }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/lib/highcharts/ipynb.py b/build/lib/highcharts/ipynb.py
new file mode 100644
index 0000000..20b4e3a
--- /dev/null
+++ b/build/lib/highcharts/ipynb.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+
+'''
+IPython notebook compatability module for highcharts-python
+
+Adapted from python-nvd3: https://github.com/areski/python-nvd3/blob/develop/nvd3/ipynb.py
+'''
+
+try:
+ _ip = get_ipython()
+except:
+ _ip = None
+if _ip and (_ip.__module__.startswith('IPython') or _ip.__module__.startswith('ipykernel')):
+
+ def _print_html(chart):
+ '''Function to return the HTML code for the div container plus the javascript
+ to generate the chart. This function is bound to the ipython formatter so that
+ charts are displayed inline.'''
+
+ return chart.iframe
+
+ def _setup_ipython_formatter(ip):
+ ''' Set up the ipython formatter to display HTML formatted output inline'''
+ from IPython import __version__ as IPython_version
+ from .highcharts.highcharts import Highchart
+ from .highmaps.highmaps import Highmap
+ from .highstock.highstock import Highstock
+
+ if IPython_version >= '0.11':
+ html_formatter = ip.display_formatter.formatters['text/html']
+
+ for chart_type in [Highchart, Highmap, Highstock]:
+ html_formatter.for_type(chart_type, _print_html)
+
+ _setup_ipython_formatter(_ip)
diff --git a/build/lib/highcharts/version.py b/build/lib/highcharts/version.py
new file mode 100644
index 0000000..1531aeb
--- /dev/null
+++ b/build/lib/highcharts/version.py
@@ -0,0 +1,7 @@
+version_info = (
+ "0",
+ "4",
+ "3"
+)
+
+__version__ = '.'.join(map(str, version_info))
diff --git a/highcharts/highcharts/highcharts.py b/highcharts/highcharts/highcharts.py
index 59e093e..6262c42 100644
--- a/highcharts/highcharts/highcharts.py
+++ b/highcharts/highcharts/highcharts.py
@@ -12,7 +12,12 @@
import datetime
import urllib.request, urllib.error, urllib.parse
import html
-from collections import Iterable
+try:
+ # works with older (3.9 and below) versions, throws an exception with newer (3.10 and above) versions
+ from collections import Iterable
+#if an import error change to trying 3.10 and above notation
+except ImportError:
+ from collections.abc import Iterable
from .options import BaseOptions, ChartOptions, ColorAxisOptions, \
ColorsOptions, CreditsOptions, DrilldownOptions, ExportingOptions, \
GlobalOptions, LabelsOptions, LangOptions, \
diff --git a/highcharts/highmaps/highmaps.py b/highcharts/highmaps/highmaps.py
index 0d73afc..f2f7b91 100644
--- a/highcharts/highmaps/highmaps.py
+++ b/highcharts/highmaps/highmaps.py
@@ -13,7 +13,12 @@
import re
import datetime
import html
-from collections import Iterable
+try:
+ # works with older (3.9 and below) versions, throws an exception with newer (3.10 and above) versions
+ from collections import Iterable
+#if an import error change to trying 3.10 and above notation
+except ImportError:
+ from collections.abc import Iterable
from .options import BaseOptions, ChartOptions, \
ColorsOptions, ColorAxisOptions, CreditsOptions, DrilldownOptions, ExportingOptions, \
GlobalOptions, LabelsOptions, LangOptions, \
diff --git a/highcharts/highstock/highstock.py b/highcharts/highstock/highstock.py
index ef8610d..9b38c2f 100644
--- a/highcharts/highstock/highstock.py
+++ b/highcharts/highstock/highstock.py
@@ -10,7 +10,12 @@
import re
import datetime
import html
-from collections import Iterable
+try:
+ # works with older (3.9 and below) versions, throws an exception with newer (3.10 and above) versions
+ from collections import Iterable
+#if an import error change to trying 3.10 and above notation
+except ImportError:
+ from collections.abc import Iterable
from .options import BaseOptions, ChartOptions, \
ColorsOptions, CreditsOptions, ExportingOptions, \
GlobalOptions, LabelsOptions, LangOptions, \
diff --git a/highcharts/version.py b/highcharts/version.py
index c8472d3..1531aeb 100644
--- a/highcharts/version.py
+++ b/highcharts/version.py
@@ -1,7 +1,7 @@
version_info = (
"0",
"4",
- "2"
+ "3"
)
__version__ = '.'.join(map(str, version_info))