11"""A python client for quickchart.io, a web service that generates static
22charts."""
33
4+ import datetime
45import json
6+ import re
57try :
68 from urllib import urlencode
79except :
810 # For Python 3
911 from urllib .parse import urlencode
1012
13+ FUNCTION_DELIMITER_RE = re .compile ('\" __BEGINFUNCTION__(.*?)__ENDFUNCTION__\" ' )
14+
15+
16+ class QuickChartFunction :
17+ def __init__ (self , script ):
18+ self .script = script
19+
20+ def __repr__ (self ):
21+ return self .script
22+
23+
24+ def serialize (obj ):
25+ if isinstance (obj , QuickChartFunction ):
26+ return '__BEGINFUNCTION__' + obj .script + '__ENDFUNCTION__'
27+ if isinstance (obj , (datetime .date , datetime .datetime )):
28+ return obj .isoformat ()
29+ return obj .__dict__
30+
31+
32+ def dump_json (obj ):
33+ ret = json .dumps (obj , default = serialize , separators = (',' , ':' ))
34+ ret = FUNCTION_DELIMITER_RE .sub (
35+ lambda match : json .loads ('"' + match .group (1 ) + '"' ), ret )
36+ return ret
37+
38+
1139class QuickChart :
1240 def __init__ (self ):
1341 self .config = None
@@ -17,15 +45,21 @@ def __init__(self):
1745 self .device_pixel_ratio = 1.0
1846 self .format = 'png'
1947 self .key = None
48+ self .scheme = 'https'
49+ self .host = 'quickchart.io'
2050
2151 def is_valid (self ):
2252 return self .config is not None
2353
54+ def get_url_base (self ):
55+ return '%s://%s' % (self .scheme , self .host )
56+
2457 def get_url (self ):
2558 if not self .is_valid ():
26- raise RuntimeError ('You must set the `config` attribute before generating a url' )
59+ raise RuntimeError (
60+ 'You must set the `config` attribute before generating a url' )
2761 params = {
28- 'c' : json . dumps (self .config ) if type (self .config ) == dict else self .config ,
62+ 'c' : dump_json (self .config ) if type (self .config ) == dict else self .config ,
2963 'w' : self .width ,
3064 'h' : self .height ,
3165 'bkg' : self .background_color ,
@@ -34,7 +68,7 @@ def get_url(self):
3468 }
3569 if self .key :
3670 params ['key' ] = self .key
37- return 'https://quickchart.io/ chart?%s' % urlencode (params )
71+ return '%s/ chart?%s' % ( self . get_url_base (), urlencode (params ) )
3872
3973 def _post (self , url ):
4074 try :
@@ -43,7 +77,7 @@ def _post(self, url):
4377 raise RuntimeError ('Could not find `requests` dependency' )
4478
4579 postdata = {
46- 'chart' : json . dumps (self .config ) if type (self .config ) == dict else self .config ,
80+ 'chart' : dump_json (self .config ) if type (self .config ) == dict else self .config ,
4781 'width' : self .width ,
4882 'height' : self .height ,
4983 'backgroundColor' : self .background_color ,
@@ -54,22 +88,23 @@ def _post(self, url):
5488 postdata ['key' ] = self .key
5589 resp = requests .post (url , json = postdata )
5690 if resp .status_code != 200 :
57- raise RuntimeError ('Invalid response code from chart creation endpoint' )
91+ raise RuntimeError (
92+ 'Invalid response code from chart creation endpoint' )
5893 return resp
5994
6095 def get_short_url (self ):
61- resp = self ._post ('https://quickchart.io/ chart/create' )
96+ resp = self ._post ('%s/ chart/create' % self . get_url_base () )
6297 parsed = json .loads (resp .text )
6398 if not parsed ['success' ]:
64- raise RuntimeError ('Failure response status from chart creation endpoint' )
99+ raise RuntimeError (
100+ 'Failure response status from chart creation endpoint' )
65101 return parsed ['url' ]
66102
67103 def get_bytes (self ):
68- resp = self ._post ('https://quickchart.io/ chart' )
104+ resp = self ._post ('%s/ chart' % self . get_url_base () )
69105 return resp .content
70106
71107 def to_file (self , path ):
72108 content = self .get_bytes ()
73109 with open (path , 'wb' ) as f :
74110 f .write (content )
75-
0 commit comments