/+junk/pygooglechart-py3k

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/%2Bjunk/pygooglechart-py3k

« back to all changes in this revision

Viewing changes to pygooglechart.py

  • Committer: gak
  • Date: 2009-03-15 07:34:55 UTC
  • Revision ID: git-v1:2ce2bd2a423b1305ad2ad81c72b69c004fecec05
Added some example helpers for MapChart

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 
4
4
http://pygooglechart.slowchop.com/
5
5
 
6
 
Copyright 2007-2009 Gerald Kaszuba
 
6
Copyright 2007-2008 Gerald Kaszuba
7
7
 
8
8
This program is free software: you can redistribute it and/or modify
9
9
it under the terms of the GNU General Public License as published by
23
23
 
24
24
import os
25
25
import urllib
26
 
import urllib.request, urllib.error
 
26
import urllib2
27
27
import math
28
28
import random
29
29
import re
33
33
# Helper variables and functions
34
34
# -----------------------------------------------------------------------------
35
35
 
36
 
__version__ = '0.3.0'
 
36
__version__ = '0.2.2'
37
37
__author__ = 'Gerald Kaszuba'
38
38
 
39
39
reo_colour = re.compile('^([A-Fa-f0-9]{2,2}){3,4}$')
85
85
class UnknownChartType(PyGoogleChartException):
86
86
    pass
87
87
 
88
 
class UnknownCountryCodeException(PyGoogleChartException):
89
 
    pass
90
88
 
91
89
# Data Classes
92
90
# -----------------------------------------------------------------------------
284
282
    of the chart. legend requires a list that corresponds to datasets.
285
283
    """
286
284
 
287
 
    BASE_URL = 'http://chart.apis.google.com/chart'
 
285
    BASE_URL = 'http://chart.apis.google.com/chart?'
288
286
    BACKGROUND = 'bg'
289
287
    CHART = 'c'
290
288
    ALPHA = 'a'
332
330
        self.markers = []
333
331
        self.line_styles = {}
334
332
        self.grid = None
335
 
        self.title_colour = None
336
 
        self.title_font_size = None
337
333
 
338
334
    # URL generation
339
335
    # -------------------------------------------------------------------------
340
 
        
 
336
 
341
337
    def get_url(self, data_class=None):
342
 
        return self.BASE_URL + '?' + self.get_url_extension(data_class)
343
 
    
344
 
    def get_url_extension(self, data_class=None):
345
338
        url_bits = self.get_url_bits(data_class=data_class)
346
 
        return '&'.join(url_bits)
 
339
        return self.BASE_URL + '&'.join(url_bits)
347
340
 
348
341
    def get_url_bits(self, data_class=None):
349
342
        url_bits = []
375
368
            url_bits.append(self.markers_to_url())        
376
369
        if self.line_styles:
377
370
            style = []
378
 
            for index in range(max(self.line_styles) + 1):
 
371
            for index in xrange(max(self.line_styles) + 1):
379
372
                if index in self.line_styles:
380
373
                    values = self.line_styles[index]
381
374
                else:
389
382
    # Downloading
390
383
    # -------------------------------------------------------------------------
391
384
 
392
 
    def download(self, file_name, use_post=True):
393
 
        if use_post:
394
 
            opener = urllib.request.urlopen(self.BASE_URL, self.get_url_extension())
395
 
        else:
396
 
            opener = urllib.request.urlopen(self.get_url())
 
385
    def download(self, file_name):
 
386
        opener = urllib2.urlopen(self.get_url())
397
387
 
398
388
        if opener.headers['content-type'] != 'image/png':
399
389
            raise BadContentTypeException('Server responded with a ' \
406
396
 
407
397
    def set_title(self, title):
408
398
        if title:
409
 
            self.title = urllib.parse.quote(title)
 
399
            self.title = urllib.quote(title)
410
400
        else:
411
401
            self.title = None
412
402
 
413
 
    def set_title_style(self, colour=None, font_size=None):
 
403
    def set_title_style(self, colour, font_size):
414
404
        if not colour is None:
415
405
            _check_colour(colour)
416
 
        if not colour and not font_size:
417
 
            return
418
 
        self.title_colour = colour or '333333'
419
 
        self.title_font_size = font_size or 13.5
 
406
        self.title_colour = colour
 
407
        self.title_font_size = font_size
420
408
 
421
409
    def set_legend(self, legend):
422
410
        """legend needs to be a list, tuple or None"""
423
411
        assert(isinstance(legend, list) or isinstance(legend, tuple) or
424
412
            legend is None)
425
413
        if legend:
426
 
            self.legend = [urllib.parse.quote(a) for a in legend]
 
414
            self.legend = [urllib.quote(a) for a in legend]
427
415
        else:
428
416
            self.legend = None
429
417
 
430
418
    def set_legend_position(self, legend_position):
431
419
        if legend_position:
432
 
            self.legend_position = urllib.parse.quote(legend_position)
 
420
            self.legend_position = urllib.quote(legend_position)
433
421
        else:    
434
422
            self.legend_position = None
435
423
 
470
458
        assert(angle >= 0 and angle <= 90)
471
459
        assert(len(args) % 2 == 0)
472
460
        args = list(args)  # args is probably a tuple and we need to mutate
473
 
        for a in range(int(len(args) / 2)):
 
461
        for a in xrange(int(len(args) / 2)):
474
462
            col = args[a * 2]
475
463
            offset = args[a * 2 + 1]
476
464
            _check_colour(col)
626
614
 
627
615
    def set_axis_labels(self, axis_type, values):
628
616
        assert(axis_type in Axis.TYPES)
629
 
        values = [urllib.parse.quote(str(a)) for a in values]
 
617
        values = [urllib.quote(str(a)) for a in values]
630
618
        axis_index = len(self.axis)
631
619
        axis = LabelAxis(axis_index, axis_type, values)
632
620
        self.axis.append(axis)
812
800
            url_bits.append('chbh=%i' % self.bar_width)
813
801
        zero_line = []
814
802
        if self.zero_lines:
815
 
            for index in range(max(self.zero_lines) + 1):
 
803
            for index in xrange(max(self.zero_lines) + 1):
816
804
                if index in self.zero_lines:
817
805
                    zero_line.append(str(self.zero_lines[index]))
818
806
                else:
906
894
                (self.__class__.__name__))
907
895
 
908
896
    def set_pie_labels(self, labels):
909
 
        self.pie_labels = [urllib.parse.quote(a) for a in labels]
 
897
        self.pie_labels = [urllib.quote(a) for a in labels]
910
898
 
911
899
    def get_url_bits(self, data_class=None):
912
900
        url_bits = Chart.get_url_bits(self, data_class=data_class)
966
954
        Chart.__init__(self, *args, **kwargs)
967
955
        self.geo_area = 'world'
968
956
        self.codes = []
969
 
        self.__areas = ('africa', 'asia', 'europe', 'middle_east',
970
 
            'south_america', 'usa', 'world')
971
 
        self.__ccodes = (
972
 
            'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO', 'AQ', 'AR',
973
 
            'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF',
974
 
            'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BR', 'BS', 'BT',
975
 
            'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI',
976
 
            'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CX', 'CY', 'CZ',
977
 
            'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER',
978
 
            'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD',
979
 
            'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR',
980
 
            'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU',
981
 
            'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE',
982
 
            'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR',
983
 
            'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT',
984
 
            'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK',
985
 
            'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV',
986
 
            'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL',
987
 
            'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH',
988
 
            'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE',
989
 
            'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH',
990
 
            'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'ST', 'SV', 'SY',
991
 
            'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN',
992
 
            'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY',
993
 
            'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE',
994
 
            'YT', 'ZA', 'ZM', 'ZW')
995
 
        
 
957
 
996
958
    def type_to_url(self):
997
959
        return 'cht=t'
998
960
 
999
961
    def set_codes(self, codes):
1000
 
        '''Set the country code map for the data.
1001
 
        Codes given in a list.
1002
 
 
1003
 
        i.e. DE - Germany
1004
 
             AT - Austria
1005
 
             US - United States
1006
 
        '''
1007
 
 
1008
 
        codemap = ''
1009
 
        
1010
 
        for cc in codes:
1011
 
            cc = cc.upper()
1012
 
            if cc in self.__ccodes:
1013
 
                codemap += cc
1014
 
            else:
1015
 
                raise UnknownCountryCodeException(cc)
1016
 
            
1017
 
        self.codes = codemap
1018
 
 
1019
 
    def set_geo_area(self, area):
1020
 
        '''Sets the geo area for the map.
1021
 
 
1022
 
        * africa
1023
 
        * asia
1024
 
        * europe
1025
 
        * middle_east
1026
 
        * south_america
1027
 
        * usa
1028
 
        * world
1029
 
        '''
1030
 
        
1031
 
        if area in self.__areas:
1032
 
            self.geo_area = area
1033
 
        else:
1034
 
            raise UnknownChartType('Unknown chart type for maps: %s' %area)
 
962
        self.codes = codes
1035
963
 
1036
964
    def get_url_bits(self, data_class=None):
1037
965
        url_bits = Chart.get_url_bits(self, data_class=data_class)
1040
968
            url_bits.append('chld=%s' % ''.join(self.codes))
1041
969
        return url_bits
1042
970
 
1043
 
    def add_data_dict(self, datadict):
1044
 
        '''Sets the data and country codes via a dictionary.
1045
 
 
1046
 
        i.e. {'DE': 50, 'GB': 30, 'AT': 70}
1047
 
        '''
1048
 
 
1049
 
        self.set_codes(datadict.keys())
1050
 
        self.add_data(datadict.values())
1051
 
 
1052
971
 
1053
972
class GoogleOMeterChart(PieChart):
1054
973
    """Inheriting from PieChart because of similar labeling"""
1077
996
    def data_to_url(self, data_class=None):
1078
997
        if not self.data:
1079
998
            raise NoDataGivenException()
1080
 
        return 'chl=%s' % urllib.parse.quote(self.data[0])
 
999
        return 'chl=%s' % urllib.quote(self.data[0])
1081
1000
 
1082
1001
    def get_url_bits(self, data_class=None):
1083
1002
        url_bits = Chart.get_url_bits(self, data_class=data_class)