src/reportlab/lib/formatters.py
author robin <robin@reportlab.com>
Tue, 07 Mar 2017 10:00:34 +0000
changeset 4330 617ffa6bbdc8
parent 4252 fe660f227cac
child 4370 823a8c33ce43
permissions -rw-r--r--
changes for release 3.4.0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
     1
#!/bin/env python
4330
617ffa6bbdc8 changes for release 3.4.0
robin <robin@reportlab.com>
parents: 4252
diff changeset
     2
#Copyright ReportLab Europe Ltd. 2000-2017
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
     3
#see license.txt for license details
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 1683
diff changeset
     4
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/lib/formatters.py
2864
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
     5
__all__=('Formatter','DecimalFormatter')
4252
fe660f227cac changes for release 3.3.0
robin
parents: 3721
diff changeset
     6
__version__='3.3.0'
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
     7
__doc__="""
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
     8
These help format numbers and dates in a user friendly way.
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
     9
Used by the graphics framework.
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    10
"""
2864
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    11
import string, sys, os, re
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    12
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    13
class Formatter:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    14
    "Base formatter - simply applies python format strings"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    15
    def __init__(self, pattern):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    16
        self.pattern = pattern
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    17
    def format(self, obj):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    18
        return self.pattern % obj
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    19
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    20
        return "%s('%s')" % (self.__class__.__name__, self.pattern)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    21
    def __call__(self, x):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    22
        return self.format(x)
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    23
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    24
2864
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    25
_ld_re=re.compile(r'^\d*\.')
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    26
_tz_re=re.compile('0+$')
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    27
class DecimalFormatter(Formatter):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    28
    """lets you specify how to build a decimal.
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    29
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    30
    A future NumberFormatter class will take Microsoft-style patterns
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    31
    instead - "$#,##0.00" is WAY easier than this."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    32
    def __init__(self, places=2, decimalSep='.', thousandSep=None, prefix=None, suffix=None):
2864
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    33
        if places=='auto':
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    34
            self.calcPlaces = self._calcPlaces
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    35
        else:
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    36
            self.places = places
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    37
        self.dot = decimalSep
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    38
        self.comma = thousandSep
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    39
        self.prefix = prefix
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    40
        self.suffix = suffix
1330
9b212b5065f6 Formatter objects added, and used for chart label formatting
andy_robinson
parents:
diff changeset
    41
2864
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    42
    def _calcPlaces(self,V):
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    43
        '''called with the full set of values to be formatted so we can calculate places'''
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    44
        self.places = max([len(_tz_re.sub('',_ld_re.sub('',str(v)))) for v in V])
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
    45
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    46
    def format(self, num):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    47
        # positivize the numbers
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    48
        sign=num<0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    49
        if sign:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    50
            num = -num
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    51
        places, sep = self.places, self.dot
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    52
        strip = places<=0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    53
        if places and strip: places = -places
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    54
        strInt = ('%.' + str(places) + 'f') % num
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    55
        if places:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    56
            strInt, strFrac = strInt.split('.')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    57
            strFrac = sep + strFrac
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    58
            if strip:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    59
                while strFrac and strFrac[-1] in ['0',sep]: strFrac = strFrac[:-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    60
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    61
            strFrac = ''
1546
1111980bdc47 Fixe broken carry for 5% of cases
rgbecker
parents: 1473
diff changeset
    62
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    63
        if self.comma is not None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    64
            strNew = ''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    65
            while strInt:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    66
                left, right = strInt[0:-3], strInt[-3:]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    67
                if left == '':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    68
                    #strNew = self.comma + right + strNew
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    69
                    strNew = right + strNew
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    70
                else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    71
                    strNew = self.comma + right + strNew
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    72
                strInt = left
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    73
            strInt = strNew
1548
c2469902b9ee Fixed up zero places case
rgbecker
parents: 1546
diff changeset
    74
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    75
        strBody = strInt + strFrac
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    76
        if sign: strBody = '-' + strBody
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    77
        if self.prefix:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    78
            strBody = self.prefix + strBody
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    79
        if self.suffix:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    80
            strBody = strBody + self.suffix
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    81
        return strBody
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
    82
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    83
    def __repr__(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    84
        return "%s(places=%d, decimalSep=%s, thousandSep=%s, prefix=%s, suffix=%s)" % (
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    85
                    self.__class__.__name__,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    86
                    self.places,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    87
                    repr(self.dot),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    88
                    repr(self.comma),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    89
                    repr(self.prefix),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    90
                    repr(self.suffix)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    91
                    )
1548
c2469902b9ee Fixed up zero places case
rgbecker
parents: 1546
diff changeset
    92
c2469902b9ee Fixed up zero places case
rgbecker
parents: 1546
diff changeset
    93
if __name__=='__main__':
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    94
    def t(n, s, places=2, decimalSep='.', thousandSep=None, prefix=None, suffix=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    95
        f=DecimalFormatter(places,decimalSep,thousandSep,prefix,suffix)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    96
        r = f(n)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    97
        print("places=%2d dot=%-4s comma=%-4s prefix=%-4s suffix=%-4s result=%10s %s" %(f.places, f.dot, f.comma, f.prefix, f.suffix,r, r==s and 'OK' or 'BAD'))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    98
    t(1000.9,'1,000.9',1,thousandSep=',')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
    99
    t(1000.95,'1,001.0',1,thousandSep=',')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   100
    t(1000.95,'1,001',-1,thousandSep=',')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   101
    t(1000.9,'1,001',0,thousandSep=',')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   102
    t(1000.9,'1000.9',1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   103
    t(1000.95,'1001.0',1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   104
    t(1000.95,'1001',-1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   105
    t(1000.9,'1001',0)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   106
    t(1000.1,'1000.1',1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   107
    t(1000.55,'1000.6',1)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1548
diff changeset
   108
    t(1000.449,'1000.4',-1)
2864
1e9a05cb3383 reportlab: add places='auto' capability to DecimalFormatter
rgbecker
parents: 2332
diff changeset
   109
    t(1000.45,'1000',0)