66
77import json
88import os
9- from typing import Optional
9+ from typing import Optional , Dict , List
1010
1111import requests
12- from validator_collection import validators
12+ from validator_collection import validators , checkers
1313
1414from highcharts_core import errors , constants
1515from highcharts_core .decorators import class_sensitive
@@ -53,6 +53,10 @@ def __init__(self, **kwargs):
5353 self ._global_options = None
5454 self ._data_options = None
5555 self ._custom_code = None
56+ self ._resources = None
57+ self ._files = None
58+ self ._css = None
59+ self ._js = None
5660
5761 self .protocol = kwargs .get ('protocol' ,
5862 os .getenv ('HIGHCHARTS_EXPORT_SERVER_PROTOCOL' ,
@@ -77,7 +81,19 @@ def __init__(self, **kwargs):
7781 self .global_options = kwargs .get ('global_options' , None )
7882 self .data_options = kwargs .get ('data_options' , None )
7983 self .custom_code = kwargs .get ('custom_code' , None )
80-
84+
85+ files = kwargs .get ('files' , None )
86+ css = kwargs .get ('css' , None )
87+ js = kwargs .get ('js' , None )
88+ resources = kwargs .get ('resources' , None )
89+
90+ if resources :
91+ self .resources = kwargs .get ('resources' , None )
92+ else :
93+ self .files = files
94+ self .css = css
95+ self .js = js
96+
8197 super ().__init__ (** kwargs )
8298
8399 @property
@@ -579,6 +595,106 @@ def custom_code(self) -> Optional[CallbackFunction]:
579595 def custom_code (self , value ):
580596 self ._custom_code = value
581597
598+ @property
599+ def resources (self ) -> Optional [Dict ]:
600+ """A dictionary of resources to be used in the export server.
601+
602+ Expects to contain up to three keys:
603+
604+ * ``files`` which contains an array of JS filenames
605+ * ``js`` which contains a string representation of JS code
606+ * ``css`` which contains a string representation of CSS code that will
607+ applied to the chart on export
608+
609+ Defaults to :obj:`None <python:None>`.
610+
611+ :rtype: :class:`dict <python:dict>` or :obj:`None <python:None>`
612+ """
613+ resources = {}
614+ if self .files :
615+ resources ['files' ] = self .files
616+ if self .js :
617+ resources ['js' ] = self .js
618+ if self .css :
619+ resources ['css' ] = self .css
620+
621+ if not resources :
622+ return None
623+
624+ return resources
625+
626+ @resources .setter
627+ def resources (self , value ):
628+ if not value :
629+ self .files = None
630+ self .js = None
631+ self .css = None
632+ elif not isinstance (value , dict ):
633+ raise errors .HighchartsValueError ('resources expects a dictionary with keys "files", "js", and "css"' )
634+ else :
635+ self .files = value .get ('files' , None )
636+ self .js = value .get ('js' , None )
637+ self .css = value .get ('css' , None )
638+
639+ @property
640+ def files (self ) -> Optional [List [str ]]:
641+ """Collection of files that will be loaded into context for the export.
642+ Defaults to :obj:`None <python:None>`.
643+
644+ :rtype: :class:`list <python:list>` of :class:`str <python:str>` or
645+ :obj:`None <python:None>`
646+ """
647+ return self ._files
648+
649+ @files .setter
650+ def files (self , value ):
651+ if not value :
652+ self ._files = None
653+ else :
654+ if isinstance (value , str ):
655+ value = [value ]
656+ elif not checkers .is_iterable (value ):
657+ raise errors .HighchartsValueError ('files expects a list of strings' )
658+
659+ self ._files = value
660+
661+ @property
662+ def js (self ) -> Optional [str ]:
663+ """JavaScript code that will be loaded into context for the exported chart.
664+ Defaults to :obj:`None <python:None>`.
665+
666+ :rtype: :class:`str <python:str>` or :obj:`None <python:None>`
667+ """
668+ return self ._js
669+
670+ @js .setter
671+ def js (self , value ):
672+ if not value :
673+ self ._js = None
674+ else :
675+ if not isinstance (value , str ):
676+ raise errors .HighchartsValueError ('js expects a string' )
677+ self ._js = value
678+
679+ @property
680+ def css (self ) -> Optional [str ]:
681+ """CSS code that will be loaded into context for the exported chart.
682+ Defaults to :obj:`None <python:None>`.
683+
684+ :rtype: :class:`str <python:str>` or :obj:`None <python:None>`
685+ """
686+ return self ._css
687+
688+ @css .setter
689+ def css (self , value ):
690+ if not value :
691+ self ._css = None
692+ else :
693+ if not isinstance (value , str ):
694+ raise errors .HighchartsValueError ('css expects a string' )
695+
696+ self ._css = value
697+
582698 @classmethod
583699 def is_export_supported (cls , options ) -> bool :
584700 """Evaluates whether the Highcharts Export Server supports exporting the series types in ``options``.
@@ -660,7 +776,8 @@ def _to_untrimmed_dict(self, in_cls = None) -> dict:
660776 'asyncRendering' : self .async_rendering ,
661777 'globalOptions' : self .global_options ,
662778 'dataOptions' : self .data_options ,
663- 'customCode' : self .custom_code
779+ 'customCode' : self .custom_code ,
780+ 'resources' : self .resources ,
664781 }
665782
666783 return untrimmed
@@ -755,6 +872,8 @@ def request_chart(self,
755872 payload ['globalOptions' ] = 'HIGHCHARTS FOR PYTHON: REPLACE WITH GLOBAL'
756873 if self .custom_code :
757874 payload ['customCode' ] = 'HIGHCHARTS FOR PYTHON: REPLACE WITH CUSTOM'
875+ if self .resources :
876+ payload ['resources' ] = self .resources
758877
759878 as_json = json .dumps (payload )
760879
0 commit comments