src/reportlab/lib/utils.py
author damian
Mon, 08 Feb 2010 18:17:33 +0000
changeset 3326 ce725978d11c
parent 3291 bd18d83b4a0d
child 3327 512eb20b0c3d
permissions -rw-r--r--
Initial Python3 compatibility fixes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2625
71abbda1f58c reportlab.lib: break out rltempfile.py to avoid rl_accel imports
rgbecker
parents: 2565
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2006
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 474
diff changeset
     2
#see license.txt for license details
2625
71abbda1f58c reportlab.lib: break out rltempfile.py to avoid rl_accel imports
rgbecker
parents: 2565
diff changeset
     3
# $URI:$
2327
c40a1b477f3f Forgot to check the exactly equal case for _startswith_rl
rgbecker
parents: 2313
diff changeset
     4
__version__=''' $Id$ '''
3029
eded59f94021 adding docstrings to lib
andy
parents: 3028
diff changeset
     5
__doc__='''Gazillions of miscellaneous internal utility functions'''
562
6c9408ec3302 Minor neglectable changes.
dinu_gherman
parents: 519
diff changeset
     6
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
     7
import os, sys, imp, time
2952
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
     8
try:
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
     9
    from hashlib import md5
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
    10
except:
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
    11
    from md5 import md5
2499
11bc8441ec51 legends.py: fix 2.1 compatibility problem
rgbecker
parents: 2497
diff changeset
    12
from reportlab.lib.logger import warnOnce
2625
71abbda1f58c reportlab.lib: break out rltempfile.py to avoid rl_accel imports
rgbecker
parents: 2565
diff changeset
    13
from rltempfile import get_rl_tempfile, get_rl_tempdir, _rl_getuid
3180
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
    14
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
    15
def isSeqType(v,_st=(tuple,list)):
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
    16
    return isinstance(v,_st)
2499
11bc8441ec51 legends.py: fix 2.1 compatibility problem
rgbecker
parents: 2497
diff changeset
    17
2259
d2738e86e6f6 True/False aren't defined for Python < 2.3
rgbecker
parents: 2258
diff changeset
    18
if sys.hexversion<0x2030000:
d2738e86e6f6 True/False aren't defined for Python < 2.3
rgbecker
parents: 2258
diff changeset
    19
    True = 1
d2738e86e6f6 True/False aren't defined for Python < 2.3
rgbecker
parents: 2258
diff changeset
    20
    False = 0
562
6c9408ec3302 Minor neglectable changes.
dinu_gherman
parents: 519
diff changeset
    21
2902
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
    22
if sys.hexversion >= 0x02000000:
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
    23
    def _digester(s):
2952
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
    24
        return md5(s).hexdigest()
2902
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
    25
else:
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
    26
    # hexdigest not available in 1.5
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
    27
    def _digester(s):
2952
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
    28
        return join(map(lambda x : "%02x" % ord(x), md5(s).digest()), '')
2902
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
    29
2215
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    30
def _findFiles(dirList,ext='.ttf'):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    31
    from os.path import isfile, isdir, join as path_join
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    32
    from os import listdir
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    33
    ext = ext.lower()
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    34
    R = []
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    35
    A = R.append
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    36
    for D in dirList:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    37
        if not isdir(D): continue
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    38
        for fn in listdir(D):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    39
            fn = path_join(D,fn)
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    40
            if isfile(fn) and (not ext or fn.lower().endswith(ext)): A(fn)
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    41
    return R
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    42
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    43
try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    44
    _UserDict = dict
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    45
except:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    46
    from UserDict import UserDict as _UserDict
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    47
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    48
class CIDict(_UserDict):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    49
    def __init__(self,*a,**kw):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    50
        map(self.update, a)
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    51
        self.update(kw)
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    52
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    53
    def update(self,D):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    54
        for k,v in D.items(): self[k] = v
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    55
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    56
    def __setitem__(self,k,v):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    57
        try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    58
            k = k.lower()
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    59
        except:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    60
            pass
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    61
        _UserDict.__setitem__(self,k,v)
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    62
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    63
    def __getitem__(self,k):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    64
        try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    65
            k = k.lower()
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    66
        except:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    67
            pass
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    68
        return _UserDict.__getitem__(self,k)
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    69
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    70
    def __delitem__(self,k):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    71
        try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    72
            k = k.lower()
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    73
        except:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    74
            pass
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    75
        return _UserDict.__delitem__(self,k)
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    76
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    77
    def get(self,k,dv=None):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    78
        try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    79
            return self[k]
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    80
        except KeyError:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    81
            return dv
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    82
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3291
diff changeset
    83
    def __contains__(self,k):
2215
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    84
        try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    85
            self[k]
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    86
            return True
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    87
        except:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    88
            return False
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    89
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    90
    def pop(self,k,*a):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    91
        try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    92
            k = k.lower()
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    93
        except:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    94
            pass
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    95
        return _UserDict.pop(*((self,k)+a))
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    96
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    97
    def setdefault(self,k,*a):
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    98
        try:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
    99
            k = k.lower()
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
   100
        except:
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
   101
            pass
e86aad9766c7 Added _findFiles & CIDict
rgbecker
parents: 2200
diff changeset
   102
        return _UserDict.setdefault(*((self,k)+a))
1837
a3920893b1b8 Back in synch, diagnostic function for distro type added
andy_robinson
parents: 1835
diff changeset
   103
1902
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   104
if os.name == 'mac':
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   105
    #with the Mac, we need to tag the file in a special
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   106
    #way so the system knows it is a PDF file.
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   107
    #This supplied by Joe Strout
2057
22e7a13fa031 Fixed so that file creator and types are now correctly set on the Mac again
rptlab
parents: 2053
diff changeset
   108
    import macfs, macostools
2007
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   109
    _KNOWN_MAC_EXT = {
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   110
        'BMP' : ('ogle','BMP '),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   111
        'EPS' : ('ogle','EPSF'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   112
        'EPSF': ('ogle','EPSF'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   113
        'GIF' : ('ogle','GIFf'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   114
        'JPG' : ('ogle','JPEG'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   115
        'JPEG': ('ogle','JPEG'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   116
        'PCT' : ('ttxt','PICT'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   117
        'PICT': ('ttxt','PICT'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   118
        'PNG' : ('ogle','PNGf'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   119
        'PPM' : ('ogle','.PPM'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   120
        'TIF' : ('ogle','TIFF'),
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   121
        'TIFF': ('ogle','TIFF'),
2051
50350756e12c Added HTML to the Mac markfilename routine - HTML files should now 'know'
johnprecedo
parents: 2045
diff changeset
   122
        'PDF' : ('CARO','PDF '),
2057
22e7a13fa031 Fixed so that file creator and types are now correctly set on the Mac again
rptlab
parents: 2053
diff changeset
   123
        'HTML': ('MSIE','TEXT'),
2007
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   124
        }
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   125
    def markfilename(filename,creatorcode=None,filetype=None,ext='PDF'):
1902
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   126
        try:
2007
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   127
            if creatorcode is None or filetype is None and ext is not None:
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   128
                try:
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   129
                    creatorcode, filetype = _KNOWN_MAC_EXT[ext.upper()]
2007
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   130
                except:
2759dd179707 Added John's mac type dict to markfilename
rgbecker
parents: 1999
diff changeset
   131
                    return
1902
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   132
            macfs.FSSpec(filename).SetCreatorType(creatorcode,filetype)
2051
50350756e12c Added HTML to the Mac markfilename routine - HTML files should now 'know'
johnprecedo
parents: 2045
diff changeset
   133
            macostools.touched(filename)
1902
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   134
        except:
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   135
            pass
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   136
else:
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   137
    def markfilename(filename,creatorcode=None,filetype=None):
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   138
        pass
3dc6869b1b47 Moved markfilename from pdfdoc
rgbecker
parents: 1837
diff changeset
   139
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   140
import reportlab
2251
afa4604d1a15 We prefer absolute RL DIR
rgbecker
parents: 2247
diff changeset
   141
__RL_DIR=os.path.dirname(reportlab.__file__)    #possibly relative
afa4604d1a15 We prefer absolute RL DIR
rgbecker
parents: 2247
diff changeset
   142
_RL_DIR=os.path.isabs(__RL_DIR) and __RL_DIR or os.path.abspath(__RL_DIR)
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   143
del reportlab
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   144
2225
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   145
#Attempt to detect if this copy of reportlab is running in a
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   146
#file system (as opposed to mostly running in a zip or McMillan
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   147
#archive or Jar file).  This is used by test cases, so that
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   148
#we can write test cases that don't get activated in a compiled
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   149
try:
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   150
    __file__
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   151
except:
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   152
    __file__ = sys.argv[0]
2305
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   153
import glob, fnmatch
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   154
try:
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   155
    _isFSD = not __loader__
2484
590938600027 utils.py: use normpath in _archive etc etc
rgbecker
parents: 2482
diff changeset
   156
    _archive = os.path.normcase(os.path.normpath(__loader__.archive))
2327
c40a1b477f3f Forgot to check the exactly equal case for _startswith_rl
rgbecker
parents: 2313
diff changeset
   157
    _archivepfx = _archive + os.sep
2484
590938600027 utils.py: use normpath in _archive etc etc
rgbecker
parents: 2482
diff changeset
   158
    _archivedir = os.path.dirname(_archive)
2327
c40a1b477f3f Forgot to check the exactly equal case for _startswith_rl
rgbecker
parents: 2313
diff changeset
   159
    _archivedirpfx = _archivedir + os.sep
2305
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   160
    _archivepfxlen = len(_archivepfx)
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   161
    _archivedirpfxlen = len(_archivedirpfx)
2352
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   162
    def __startswith_rl(fn,
2484
590938600027 utils.py: use normpath in _archive etc etc
rgbecker
parents: 2482
diff changeset
   163
                    _archivepfx=_archivepfx,
590938600027 utils.py: use normpath in _archive etc etc
rgbecker
parents: 2482
diff changeset
   164
                    _archivedirpfx=_archivedirpfx,
590938600027 utils.py: use normpath in _archive etc etc
rgbecker
parents: 2482
diff changeset
   165
                    _archive=_archive,
590938600027 utils.py: use normpath in _archive etc etc
rgbecker
parents: 2482
diff changeset
   166
                    _archivedir=_archivedir,
2352
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   167
                    os_path_normpath=os.path.normpath,
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   168
                    os_path_normcase=os.path.normcase,
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   169
                    os_getcwd=os.getcwd,
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   170
                    os_sep=os.sep,
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   171
                    os_sep_len = len(os.sep)):
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   172
        '''if the name starts with a known prefix strip it off'''
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   173
        fn = os_path_normpath(fn.replace('/',os_sep))
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   174
        nfn = os_path_normcase(fn)
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   175
        if nfn in (_archivedir,_archive): return 1,''
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   176
        if nfn.startswith(_archivepfx): return 1,fn[_archivepfxlen:]
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   177
        if nfn.startswith(_archivedirpfx): return 1,fn[_archivedirpfxlen:]
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   178
        cwd = os_path_normcase(os_getcwd())
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   179
        n = len(cwd)
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   180
        if nfn.startswith(cwd):
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   181
            if fn[n:].startswith(os_sep): return 1, fn[n+os_sep_len:]
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   182
            if n==len(fn): return 1,''
c8bf2490acc9 Another know location
rgbecker
parents: 2340
diff changeset
   183
        return not os.path.isabs(fn),fn
2305
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   184
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   185
    def _startswith_rl(fn):
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   186
        return __startswith_rl(fn)[1]
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   187
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   188
    def rl_glob(pattern,glob=glob.glob,fnmatch=fnmatch.fnmatch, _RL_DIR=_RL_DIR,pjoin=os.path.join):
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   189
        c, pfn = __startswith_rl(pattern)
2307
a1f106a7bed8 More compact distro changes
rgbecker
parents: 2305
diff changeset
   190
        r = glob(pfn)
2305
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   191
        if c or r==[]:
2307
a1f106a7bed8 More compact distro changes
rgbecker
parents: 2305
diff changeset
   192
            r += map(lambda x,D=_archivepfx,pjoin=pjoin: pjoin(_archivepfx,x),filter(lambda x,pfn=pfn,fnmatch=fnmatch: fnmatch(x,pfn),__loader__._files.keys()))
2305
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   193
        return r
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   194
except:
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   195
    _isFSD = os.path.isfile(__file__)   #slight risk of wrong path
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   196
    __loader__ = None
2305
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   197
    def _startswith_rl(fn):
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   198
        return fn
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   199
    def rl_glob(pattern,glob=glob.glob):
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   200
        return glob(pattern)
3dbfbe55e9ff Use more advanced __loader__ friendly code
rgbecker
parents: 2302
diff changeset
   201
del glob, fnmatch
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   202
_isFSSD = _isFSD and os.path.isfile(os.path.splitext(__file__)[0] +'.py')
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   203
1837
a3920893b1b8 Back in synch, diagnostic function for distro type added
andy_robinson
parents: 1835
diff changeset
   204
def isFileSystemDistro():
2225
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   205
    '''return truth if a file system distribution'''
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   206
    return _isFSD
1837
a3920893b1b8 Back in synch, diagnostic function for distro type added
andy_robinson
parents: 1835
diff changeset
   207
a3920893b1b8 Back in synch, diagnostic function for distro type added
andy_robinson
parents: 1835
diff changeset
   208
def isCompactDistro():
2225
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   209
    '''return truth if not a file system distribution'''
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   210
    return not _isFSD
1837
a3920893b1b8 Back in synch, diagnostic function for distro type added
andy_robinson
parents: 1835
diff changeset
   211
a3920893b1b8 Back in synch, diagnostic function for distro type added
andy_robinson
parents: 1835
diff changeset
   212
def isSourceDistro():
2225
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   213
    '''return truth if a source file system distribution'''
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   214
    return _isFSSD
1143
46a5ec2d3d2c Better import error checking
rgbecker
parents: 998
diff changeset
   215
413
6312e8296c9b Initial version
rgbecker
parents:
diff changeset
   216
try:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   217
    #raise ImportError
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   218
    ### NOTE!  FP_STR SHOULD PROBABLY ALWAYS DO A PYTHON STR() CONVERSION ON ARGS
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   219
    ### IN CASE THEY ARE "LAZY OBJECTS".  ACCELLERATOR DOESN'T DO THIS (YET)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   220
    try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   221
        from _rl_accel import fp_str                # in case of builtin version
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2051
diff changeset
   222
    except ImportError:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   223
        from reportlab.lib._rl_accel import fp_str  # specific
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2051
diff changeset
   224
except ImportError:
2139
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   225
    from math import log
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   226
    _log_10 = lambda x,log=log,_log_e_10=log(10.0): log(x)/_log_e_10
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   227
    _fp_fmts = "%.0f", "%.1f", "%.2f", "%.3f", "%.4f", "%.5f", "%.6f"
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   228
    import re
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   229
    _tz_re = re.compile('0+$')
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   230
    del re
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   231
    def fp_str(*a):
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   232
        '''convert separate arguments (or single sequence arg) into space separated numeric strings'''
2499
11bc8441ec51 legends.py: fix 2.1 compatibility problem
rgbecker
parents: 2497
diff changeset
   233
        if len(a)==1 and isSeqType(a[0]): a = a[0]
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   234
        s = []
2139
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   235
        A = s.append
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   236
        for i in a:
2139
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   237
            sa =abs(i)
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   238
            if sa<=1e-7: A('0')
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   239
            else:
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   240
                l = sa<=1 and 6 or min(max(0,(6-int(_log_10(sa)))),6)
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   241
                n = _fp_fmts[l]%i
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   242
                if l:
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   243
                    n = _tz_re.sub('',n)
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   244
                    try:
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   245
                        if n[-1]=='.': n = n[:-1]
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   246
                    except:
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   247
                        print i, n
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   248
                        raise
0f27f8cb5586 Make fp_str more like _rl_accel(C/java) versions
rgbecker
parents: 2133
diff changeset
   249
                A((n[0]!='0' or len(n)==1) and n or n[1:])
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   250
        return ' '.join(s)
448
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   251
981
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
   252
#hack test for comma users
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
   253
if ',' in fp_str(0.25):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   254
    _FP_STR = fp_str
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   255
    def fp_str(*a):
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   256
        return _FP_STR(*a).replace(',','.')
981
b3dfa2ba427c Attempt to fix the locale mismatch problem
rgbecker
parents: 962
diff changeset
   257
1821
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   258
def recursiveImport(modulename, baseDir=None, noCWD=0, debug=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   259
    """Dynamically imports possible packagized module, or raises ImportError"""
2160
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   260
    normalize = lambda x: os.path.normcase(os.path.abspath(os.path.normpath(x)))
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   261
    path = map(normalize,sys.path)
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   262
    if baseDir:
2499
11bc8441ec51 legends.py: fix 2.1 compatibility problem
rgbecker
parents: 2497
diff changeset
   263
        if not isSeqType(baseDir):
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   264
            tp = [baseDir]
1833
135322abc191 Fix recursivImport for case when baseDir is a sequence
rgbecker
parents: 1821
diff changeset
   265
        else:
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   266
            tp = filter(None,list(baseDir))
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   267
        for p in tp:
2160
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   268
            p = normalize(p)
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   269
            if p not in path: path.insert(0,p)
1396
40d1361f08b7 Enhanced the error message from recursiveImport
andy_robinson
parents: 1389
diff changeset
   270
1821
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   271
    if noCWD:
2160
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   272
        for p in ('','.',normalize('.')):
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   273
            while p in path:
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   274
                if debug: print 'removed "%s" from path' % p
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   275
                path.remove(p)
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   276
    elif '.' not in path:
1821
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   277
            path.insert(0,'.')
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   278
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   279
    if debug:
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   280
        import pprint
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   281
        pp = pprint.pprint
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   282
        print 'path=',
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   283
        pp(path)
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2160
diff changeset
   284
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   285
    #make import errors a bit more informative
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   286
    opath = sys.path
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   287
    try:
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   288
        sys.path = path
2160
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   289
        exec 'import %s\nm = %s\n' % (modulename,modulename) in locals()
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   290
        sys.path = opath
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   291
        return m
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   292
    except ImportError:
2160
0ac717b8d778 Minor changes to recursiveimport
rgbecker
parents: 2156
diff changeset
   293
        sys.path = opath
2156
e0398bc717f2 First attempt at using import rather than imp
rgbecker
parents: 2139
diff changeset
   294
        msg = "recursiveimport(%s,baseDir=%s) failed" % (modulename,baseDir)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   295
        if baseDir:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3291
diff changeset
   296
            msg = msg + " under paths '%s'" % repr(path)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   297
        raise ImportError, msg
1396
40d1361f08b7 Enhanced the error message from recursiveImport
andy_robinson
parents: 1389
diff changeset
   298
1821
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   299
def recursiveGetAttr(obj, name):
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   300
    "Can call down into e.g. object1.object2[4].attr"
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   301
    return eval(name, obj.__dict__)
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   302
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   303
def recursiveSetAttr(obj, name, value):
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   304
    "Can call down into e.g. object1.object2[4].attr = value"
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   305
    #get the thing above last.
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   306
    tokens = name.split('.')
1821
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   307
    if len(tokens) == 1:
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   308
        setattr(obj, name, value)
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2160
diff changeset
   309
    else:
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   310
        most = '.'.join(tokens[:-1])
1821
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   311
        last = tokens[-1]
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   312
        parent = recursiveGetAttr(obj, most)
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   313
        setattr(parent, last, value)
7854ddd0fc30 Fixed recursive import, setting and gettign attributes
andy_robinson
parents: 1683
diff changeset
   314
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
   315
def import_zlib():
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   316
    try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   317
        import zlib
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2051
diff changeset
   318
    except ImportError:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   319
        zlib = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   320
        from reportlab.rl_config import ZLIB_WARNINGS
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   321
        if ZLIB_WARNINGS: warnOnce('zlib not available')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   322
    return zlib
674
c25a9dbfc27a Improved ImportError handling
rgbecker
parents: 562
diff changeset
   323
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   324
# Image Capability Detection.  Set a flag haveImages
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   325
# to tell us if either PIL or Java imaging libraries present.
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   326
# define PIL_Image as either None, or an alias for the PIL.Image
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   327
# module, as there are 2 ways to import it
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   328
if sys.platform[0:4] == 'java':
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   329
    try:
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   330
        import javax.imageio
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   331
        import java.awt.image
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   332
        haveImages = 1
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   333
    except:
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   334
        haveImages = 0
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   335
else:
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   336
    try:
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   337
        from PIL import Image
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2051
diff changeset
   338
    except ImportError:
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   339
        try:
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   340
            import Image
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2051
diff changeset
   341
        except ImportError:
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   342
            Image = None
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   343
    haveImages = Image is not None
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   344
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   345
try:
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   346
    from cStringIO import StringIO as __StringIO
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   347
except ImportError:
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   348
    from StringIO import StringIO as __StringIO
1580
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   349
def getStringIO(buf=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   350
    '''unified StringIO instance interface'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   351
    return buf is not None and __StringIO(buf) or __StringIO()
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   352
_StringIOKlass=__StringIO().__class__
1580
50792f072538 use generalised StringIO instance interface
rgbecker
parents: 1575
diff changeset
   353
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   354
class ArgvDictValue:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   355
    '''A type to allow clients of getArgvDict to specify a conversion function'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   356
    def __init__(self,value,func):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   357
        self.value = value
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   358
        self.func = func
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   359
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   360
def getArgvDict(**kw):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   361
    ''' Builds a dictionary from its keyword arguments with overrides from sys.argv.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   362
        Attempts to be smart about conversions, but the value can be an instance
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   363
        of ArgDictValue to allow specifying a conversion function.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   364
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   365
    def handleValue(v,av,func):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   366
        if func:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   367
            v = func(av)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   368
        else:
3180
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
   369
            if isinstance(v,basestring):
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
   370
                if isinstance(v,unicode): v = v.encode('utf8')
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   371
                v = av
3180
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
   372
            elif isinstance(v,float):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   373
                v = float(av)
3180
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
   374
            elif isinstance(v,int):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   375
                v = int(av)
3180
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
   376
            elif isinstance(v,list):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   377
                v = list(eval(av))
3180
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
   378
            elif isinstance(v,tuple):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   379
                v = tuple(eval(av))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   380
            else:
3180
349e9644fce8 reportlab: attempt to remove type() checking in favour of isinstance
rgbecker
parents: 3171
diff changeset
   381
                raise TypeError("Can't convert string %r to %s" % (av,type(v)))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   382
        return v
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   383
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   384
    A = sys.argv[1:]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   385
    R = {}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   386
    for k, v in kw.items():
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   387
        if isinstance(v,ArgvDictValue):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   388
            v, func = v.value, v.func
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   389
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   390
            func = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   391
        handled = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   392
        ke = k+'='
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   393
        for a in A:
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   394
            if a.find(ke)==0:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   395
                av = a[len(ke):]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   396
                A.remove(a)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   397
                R[k] = handleValue(v,av,func)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   398
                handled = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   399
                break
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   400
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   401
        if not handled: R[k] = handleValue(v,v,func)
1387
715edbf17c7a Improved argv stuff
rgbecker
parents: 1375
diff changeset
   402
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   403
    return R
1375
cb8e4098def5 Added ArgvDictValue and getArgvDict
rgbecker
parents: 1153
diff changeset
   404
452
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   405
def getHyphenater(hDict=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   406
    try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   407
        from reportlab.lib.pyHnj import Hyphen
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   408
        if hDict is None: hDict=os.path.join(os.path.dirname(__file__),'hyphen.mashed')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   409
        return Hyphen(hDict)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   410
    except ImportError, errMsg:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   411
        if str(errMsg)!='No module named pyHnj': raise
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   412
        return None
452
6bb011a0d63e Initial version of D Yoo's pyHnj
rgbecker
parents: 448
diff changeset
   413
448
cb0c4d97e29b Added _className func
rgbecker
parents: 413
diff changeset
   414
def _className(self):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   415
    '''Return a shortened class name'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   416
    try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   417
        name = self.__class__.__name__
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   418
        i=name.rfind('.')
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   419
        if i>=0: return name[i+1:]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   420
        return name
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   421
    except AttributeError:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   422
        return str(self)
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   423
2309
47243845ef50 Attempt to fix open_for_read again
rgbecker
parents: 2307
diff changeset
   424
def open_for_read_by_name(name,mode='b'):
47243845ef50 Attempt to fix open_for_read again
rgbecker
parents: 2307
diff changeset
   425
    if 'r' not in mode: mode = 'r'+mode
47243845ef50 Attempt to fix open_for_read again
rgbecker
parents: 2307
diff changeset
   426
    try:
47243845ef50 Attempt to fix open_for_read again
rgbecker
parents: 2307
diff changeset
   427
        return open(name,mode)
47243845ef50 Attempt to fix open_for_read again
rgbecker
parents: 2307
diff changeset
   428
    except IOError:
47243845ef50 Attempt to fix open_for_read again
rgbecker
parents: 2307
diff changeset
   429
        if _isFSD or __loader__ is None: raise
2313
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   430
        #we have a __loader__, perhaps the filename starts with
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   431
        #the dirname(reportlab.__file__) or is relative
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   432
        name = _startswith_rl(name)
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   433
        s = __loader__.get_data(name)
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   434
        if 'b' not in mode and os.linesep!='\n': s = s.replace(os.linesep,'\n')
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   435
        return getStringIO(s)
2309
47243845ef50 Attempt to fix open_for_read again
rgbecker
parents: 2307
diff changeset
   436
2313
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   437
import urllib
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   438
def open_for_read(name,mode='b', urlopen=urllib.urlopen):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   439
    '''attempt to open a file or URL for reading'''
2229
99cb312c5269 Fix transparency & jpeg behaviour
rgbecker
parents: 2227
diff changeset
   440
    if hasattr(name,'read'): return name
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   441
    try:
2313
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   442
        return open_for_read_by_name(name,mode)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   443
    except:
2313
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   444
        try:
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   445
            return getStringIO(urlopen(name).read())
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   446
        except:
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   447
            raise IOError('Cannot open resource "%s"' % name)
e823a147f0b5 Another rework of the open for read code
rgbecker
parents: 2309
diff changeset
   448
del urllib
1575
7d2360bdfc4d Added open_for_read
rgbecker
parents: 1561
diff changeset
   449
2225
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   450
def open_and_read(name,mode='b'):
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   451
    return open_for_read(name,mode).read()
783cbac215e5 Improve the fs distro check
rgbecker
parents: 2215
diff changeset
   452
2247
256cea0756a9 Added open_and_readlines
rgbecker
parents: 2244
diff changeset
   453
def open_and_readlines(name,mode='t'):
256cea0756a9 Added open_and_readlines
rgbecker
parents: 2244
diff changeset
   454
    return open_and_read(name,mode).split('\n')
256cea0756a9 Added open_and_readlines
rgbecker
parents: 2244
diff changeset
   455
2240
068e2487e780 Added rl_isfile
rgbecker
parents: 2231
diff changeset
   456
def rl_isfile(fn,os_path_isfile=os.path.isfile):
068e2487e780 Added rl_isfile
rgbecker
parents: 2231
diff changeset
   457
    if hasattr(fn,'read'): return True
068e2487e780 Added rl_isfile
rgbecker
parents: 2231
diff changeset
   458
    if os_path_isfile(fn): return True
068e2487e780 Added rl_isfile
rgbecker
parents: 2231
diff changeset
   459
    if _isFSD or __loader__ is None: return False
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   460
    fn = _startswith_rl(fn)
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   461
    return fn in __loader__._files.keys()
2240
068e2487e780 Added rl_isfile
rgbecker
parents: 2231
diff changeset
   462
2339
4b1dae4bd1a8 More changes related to compact distro path recognition
rgbecker
parents: 2332
diff changeset
   463
def rl_isdir(pn,os_path_isdir=os.path.isdir,os_path_normpath=os.path.normpath):
2244
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   464
    if os_path_isdir(pn): return True
58148991bc4d Improvements for compact running
rgbecker
parents: 2240
diff changeset
   465
    if _isFSD or __loader__ is None: return False
2354
c20a2fe18b0e reportlab.lib.utils fix rl_isdir
rgbecker
parents: 2352
diff changeset
   466
    pn = _startswith_rl(os_path_normpath(pn))
c20a2fe18b0e reportlab.lib.utils fix rl_isdir
rgbecker
parents: 2352
diff changeset
   467
    if not pn.endswith(os.sep): pn += os.sep
2258
08e55f5390cc Remove things that python 2.1 fails on
rgbecker
parents: 2256
diff changeset
   468
    return len(filter(lambda x,pn=pn: x.startswith(pn),__loader__._files.keys()))>0
2240
068e2487e780 Added rl_isfile
rgbecker
parents: 2231
diff changeset
   469
2794
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   470
def rl_listdir(pn,os_path_isdir=os.path.isdir,os_path_normpath=os.path.normpath,os_listdir=os.listdir):
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   471
    if os_path_isdir(pn) or _isFSD or __loader__ is None: return os_listdir(pn)
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   472
    pn = _startswith_rl(os_path_normpath(pn))
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   473
    if not pn.endswith(os.sep): pn += os.sep
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   474
    return [x[len(pn):] for x in __loader__._files.keys() if x.startswith(pn)]
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   475
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   476
def rl_getmtime(pn,os_path_isfile=os.path.isfile,os_path_normpath=os.path.normpath,os_path_getmtime=os.path.getmtime,time_mktime=time.mktime):
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   477
    if os_path_isfile(pn) or _isFSD or __loader__ is None: return os_path_getmtime(pn)
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   478
    p = _startswith_rl(os_path_normpath(pn))
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   479
    try:
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   480
        e = __loader__._files[p]
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   481
    except KeyError:
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   482
        return os_path_getmtime(pn)
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   483
    s = e[5]
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   484
    d = e[6]
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   485
    y = ((d>>9)&0x7f)+1980
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   486
    m = (d>>5)&0xf
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   487
    d &= 0x1f
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   488
    h = (s>>11)&0xf
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   489
    m = (s>>5)&0x3f
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   490
    s &= 0x1f
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   491
    s <<= 1
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   492
    return time_mktime((y,m,d,h,m,s,0,0,0))
6539e5dc77b8 add support for fontfinder in zip distribution
rgbecker
parents: 2764
diff changeset
   493
2301
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   494
def rl_get_module(name,dir):
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3291
diff changeset
   495
    if name in sys.modules:
2301
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   496
        om = sys.modules[name]
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   497
        del sys.modules[name]
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   498
    else:
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   499
        om = None
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   500
    try:
2302
240a26f9ee8f rl_get_module now seems to work as intended
rgbecker
parents: 2301
diff changeset
   501
        f = None
2301
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   502
        try:
2302
240a26f9ee8f rl_get_module now seems to work as intended
rgbecker
parents: 2301
diff changeset
   503
            f, p, desc= imp.find_module(name,[dir])
2301
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   504
            return imp.load_module(name,f,p,desc)
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   505
        except:
2307
a1f106a7bed8 More compact distro changes
rgbecker
parents: 2305
diff changeset
   506
            if isCompactDistro():
2301
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   507
                #attempt a load from inside the zip archive
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   508
                import zipimport
2307
a1f106a7bed8 More compact distro changes
rgbecker
parents: 2305
diff changeset
   509
                dir = _startswith_rl(dir)
2356
4a71278dd82d Minor fixes to lib.utils.rl_get_module
rgbecker
parents: 2354
diff changeset
   510
                dir = (dir=='.' or not dir) and _archive or os.path.join(_archive,dir.replace('/',os.sep))
2327
c40a1b477f3f Forgot to check the exactly equal case for _startswith_rl
rgbecker
parents: 2313
diff changeset
   511
                zi = zipimport.zipimporter(dir)
2301
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   512
                return zi.load_module(name)
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   513
            raise ImportError('%s[%s]' % (name,dir))
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   514
    finally:
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   515
        if om: sys.modules[name] = om
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   516
        del om
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   517
        if f: f.close()
3df8c1c14c0e rl_get_module added
rgbecker
parents: 2300
diff changeset
   518
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   519
def _isPILImage(im):
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   520
    try:
3291
bd18d83b4a0d utils.py: hack fix for load problem in PIL 1.1.7
rgbecker
parents: 3253
diff changeset
   521
        return isinstance(im,Image.Image)
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   522
    except ImportError:
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   523
        return 0
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   524
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   525
class ImageReader(object):
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   526
    "Wraps up either PIL or Java to get data from bitmaps"
2952
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
   527
    _cache={}
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   528
    def __init__(self, fileName):
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   529
        if isinstance(fileName,ImageReader):
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   530
            self.__dict__ = fileName.__dict__   #borgize
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   531
            return
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   532
        #start wih lots of null private fields, to be populated by
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   533
        #the relevant engine.
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   534
        self.fileName = fileName
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   535
        self._image = None
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   536
        self._width = None
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   537
        self._height = None
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   538
        self._transparent = None
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   539
        self._data = None
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   540
        if _isPILImage(fileName):
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   541
            self._image = fileName
2902
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
   542
            self.fp = getattr(fileName,'fp',None)
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   543
            try:
2720
2c04d204766d utils.py: attempt to fix fileName from PIL images
rgbecker
parents: 2716
diff changeset
   544
                self.fileName = self._image.fileName
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   545
            except AttributeError:
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   546
                self.fileName = 'PILIMAGE_%d' % id(self)
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   547
        else:
2556
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   548
            try:
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   549
                from reportlab.rl_config import imageReaderFlags
2556
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   550
                self.fp = open_for_read(fileName,'b')
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   551
                if isinstance(self.fp,_StringIOKlass):  imageReaderFlags=0 #avoid messing with already internal files
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   552
                if imageReaderFlags>0:  #interning
2952
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
   553
                    data = self.fp.read()
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   554
                    if imageReaderFlags&2:  #autoclose
2952
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
   555
                        try:
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
   556
                            self.fp.close()
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
   557
                        except:
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
   558
                            pass
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   559
                    if imageReaderFlags&4:  #cache the data
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   560
                        if not self._cache:
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   561
                            from rl_config import register_reset
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   562
                            register_reset(self._cache.clear)
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   563
                        data=self._cache.setdefault(md5(data).digest(),data)
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   564
                    self.fp=getStringIO(data)
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   565
                elif imageReaderFlags==-1 and isinstance(fileName,(str,unicode)):
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   566
                    #try Ralf Schmitt's re-opening technique of avoiding too many open files
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   567
                    self.fp.close()
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   568
                    del self.fp #will become a property in the next statement
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   569
                    self.__class__=LazyImageReader
2953
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   570
                if haveImages:
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   571
                    #detect which library we are using and open the image
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   572
                    if not self._image:
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   573
                        self._image = self._read_image(self.fp)
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   574
                    if getattr(self._image,'format',None)=='JPEG': self.jpeg_fh = self._jpeg_fh
2953
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   575
                else:
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   576
                    from reportlab.pdfbase.pdfutils import readJPEGInfo
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   577
                    try:
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   578
                        self._width,self._height,c=readJPEGInfo(self.fp)
2952
8a51cf037687 reportlab: add rl_config.internImageFiles and extra support in ImageReader
rgbecker
parents: 2942
diff changeset
   579
                    except:
2953
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   580
                        raise RuntimeError('Imaging Library not available, unable to import bitmaps only jpegs')
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   581
                    self.jpeg_fh = self._jpeg_fh
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   582
                    self._data = self.fp.read()
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   583
                    self._dataA=None
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   584
                    self.fp.seek(0)
2556
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   585
            except:
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   586
                et,ev,tb = sys.exc_info()
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   587
                if hasattr(ev,'args'):
2953
59f221d6007c reportlab: improve ImageReader so it works with Image flowables in the absence of PIL
rgbecker
parents: 2952
diff changeset
   588
                    a = str(ev.args[-1])+(' fileName=%r'%fileName)
2556
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   589
                    ev.args= ev.args[:-1]+(a,)
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   590
                    raise et,ev,tb
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   591
                else:
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   592
                    raise
d7c3c6b74053 utils.py: annotate ImageReader read errors
rgbecker
parents: 2502
diff changeset
   593
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   594
    def _read_image(self,fp):
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   595
        if sys.platform[0:4] == 'java':
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   596
            from javax.imageio import ImageIO
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   597
            return ImageIO.read(fp)
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   598
        else:
3291
bd18d83b4a0d utils.py: hack fix for load problem in PIL 1.1.7
rgbecker
parents: 3253
diff changeset
   599
            return Image.open(fp)
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   600
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   601
    def _jpeg_fh(self):
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   602
        fp = self.fp
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   603
        fp.seek(0)
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   604
        return fp
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   605
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   606
    def jpeg_fh(self):
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   607
        return None
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   608
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   609
    def getSize(self):
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   610
        if (self._width is None or self._height is None):
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   611
            if sys.platform[0:4] == 'java':
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   612
                self._width = self._image.getWidth()
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   613
                self._height = self._image.getHeight()
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   614
            else:
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   615
                self._width, self._height = self._image.size
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   616
        return (self._width, self._height)
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2160
diff changeset
   617
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   618
    def getRGBData(self):
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   619
        "Return byte array of RGB data as string"
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   620
        if self._data is None:
2902
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
   621
            self._dataA = None
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   622
            if sys.platform[0:4] == 'java':
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   623
                import jarray
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   624
                from java.awt.image import PixelGrabber
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   625
                width, height = self.getSize()
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   626
                buffer = jarray.zeros(width*height, 'i')
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   627
                pg = PixelGrabber(self._image, 0,0,width,height,buffer,0,width)
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   628
                pg.grabPixels()
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   629
                # there must be a way to do this with a cast not a byte-level loop,
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   630
                # I just haven't found it yet...
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   631
                pixels = []
2059
e5eec1dd6f0c ImageReader can now take File objects as well as Strings
dragan1
parents: 2057
diff changeset
   632
                a = pixels.append
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   633
                for i in range(len(buffer)):
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   634
                    rgb = buffer[i]
2087
5c4b76884d9d fixed java file read bug
dragan1
parents: 2086
diff changeset
   635
                    a(chr((rgb>>16)&0xff))
5c4b76884d9d fixed java file read bug
dragan1
parents: 2086
diff changeset
   636
                    a(chr((rgb>>8)&0xff))
2059
e5eec1dd6f0c ImageReader can now take File objects as well as Strings
dragan1
parents: 2057
diff changeset
   637
                    a(chr(rgb&0xff))
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   638
                self._data = ''.join(pixels)
2482
4ae04d1800af CMYK image improvements
rgbecker
parents: 2479
diff changeset
   639
                self.mode = 'RGB'
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   640
            else:
2482
4ae04d1800af CMYK image improvements
rgbecker
parents: 2479
diff changeset
   641
                im = self._image
4ae04d1800af CMYK image improvements
rgbecker
parents: 2479
diff changeset
   642
                mode = self.mode = im.mode
2902
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
   643
                if mode=='RGBA':
3291
bd18d83b4a0d utils.py: hack fix for load problem in PIL 1.1.7
rgbecker
parents: 3253
diff changeset
   644
                    if Image.VERSION.startswith('1.1.7'): im.load()
2902
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
   645
                    self._dataA = ImageReader(im.split()[3])
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
   646
                    im = im.convert('RGB')
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
   647
                    self.mode = 'RGB'
f15ac27dc73f reportlab: add in RGBA functionality for sensible images
rgbecker
parents: 2838
diff changeset
   648
                elif mode not in ('L','RGB','CMYK'):
2482
4ae04d1800af CMYK image improvements
rgbecker
parents: 2479
diff changeset
   649
                    im = im.convert('RGB')
4ae04d1800af CMYK image improvements
rgbecker
parents: 2479
diff changeset
   650
                    self.mode = 'RGB'
4ae04d1800af CMYK image improvements
rgbecker
parents: 2479
diff changeset
   651
                self._data = im.tostring()
2200
be0cfccc662a Fixed up tabs and whitespace in all source files
andy_robinson
parents: 2160
diff changeset
   652
        return self._data
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   653
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   654
    def getImageData(self):
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   655
        width, height = self.getSize()
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   656
        return width, height, self.getRGBData()
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   657
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   658
    def getTransparent(self):
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   659
        if sys.platform[0:4] == 'java':
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   660
            return None
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   661
        else:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3291
diff changeset
   662
            if "transparency" in self._image.info:
2045
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   663
                transparency = self._image.info["transparency"] * 3
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   664
                palette = self._image.palette
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   665
                try:
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   666
                    palette = palette.palette
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   667
                except:
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   668
                    palette = palette.data
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   669
                return map(ord, palette[transparency:transparency+3])
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   670
            else:
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   671
                return None
cc042609c62e hack to ImageReader
rgbecker
parents: 2044
diff changeset
   672
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   673
class LazyImageReader(ImageReader): 
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   674
    def fp(self): 
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   675
        return open_for_read(self.fileName, 'b') 
3083
95f7752b0284 reportlab: remove 2.3/2.4 blockers
rgbecker
parents: 3029
diff changeset
   676
    fp=property(fp) 
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   677
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   678
    def _image(self):
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   679
        return self._read_image(self.fp)
3083
95f7752b0284 reportlab: remove 2.3/2.4 blockers
rgbecker
parents: 3029
diff changeset
   680
    _image=property(_image) 
2954
5ec6485e810a reportlab: implement Ralf Schmitt's open files limiter
rgbecker
parents: 2953
diff changeset
   681
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   682
def getImageData(imageFileName):
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   683
    "Get width, height and RGB pixels from image file.  Wraps Java/PIL"
2487
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   684
    try:
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   685
        return imageFileName.getImageData()
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   686
    except AttributeError:
a51bf871b709 reportlab: better support for PIL image
rgbecker
parents: 2484
diff changeset
   687
        return ImageReader(imageFileName).getImageData()
2044
3be472f4a6dd Various work on abstracting out images, plus outstanding patches
andy_robinson
parents: 2007
diff changeset
   688
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   689
class DebugMemo:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   690
    '''Intended as a simple report back encapsulator
1545
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   691
3028
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   692
    Typical usages:
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   693
        
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   694
    1. To record error data::
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   695
        
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   696
        dbg = DebugMemo(fn='dbgmemo.dbg',myVar=value)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   697
        dbg.add(anotherPayload='aaaa',andagain='bbb')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   698
        dbg.dump()
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   699
3028
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   700
    2. To show the recorded info::
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   701
        
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   702
        dbg = DebugMemo(fn='dbgmemo.dbg',mode='r')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   703
        dbg.load()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   704
        dbg.show()
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   705
3028
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   706
    3. To re-use recorded information::
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   707
        
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   708
        dbg = DebugMemo(fn='dbgmemo.dbg',mode='r')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   709
            dbg.load()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   710
        myTestFunc(dbg.payload('myVar'),dbg.payload('andagain'))
1545
966ccacc4c7d Changes to DebugMemo.__doc__
rgbecker
parents: 1543
diff changeset
   711
3028
082f5208644e docstring modifications to adhere to restructuredtext
damian
parents: 2964
diff changeset
   712
    In addition to the payload variables the dump records many useful bits
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   713
    of information which are also printed in the show() method.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   714
    '''
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   715
    def __init__(self,fn='rl_dbgmemo.dbg',mode='w',getScript=1,modules=(),capture_traceback=1, stdout=None, **kw):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   716
        import time, socket
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   717
        self.fn = fn
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   718
        if not stdout: 
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   719
            self.stdout = sys.stdout
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   720
        else:
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   721
            if hasattr(stdout,'write'):
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   722
                self.stdout = stdout
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   723
            else:
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   724
                self.stdout = open(stdout,'w')
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   725
        if mode!='w': return
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   726
        self.store = store = {}
2296
8f5419265559 Added capture_traceback=1 to DebugMemo init
rgbecker
parents: 2279
diff changeset
   727
        if capture_traceback and sys.exc_info() != (None,None,None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   728
            import traceback
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   729
            s = getStringIO()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   730
            traceback.print_exc(None,s)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   731
            store['__traceback'] = s.getvalue()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   732
        cwd=os.getcwd()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   733
        lcwd = os.listdir(cwd)
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   734
        pcwd = os.path.dirname(cwd)
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   735
        lpcwd = pcwd and os.listdir(pcwd) or '???'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   736
        exed = os.path.abspath(os.path.dirname(sys.argv[0]))
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   737
        project_version='???'
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   738
        md=None
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   739
        try:
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   740
            import marshal
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   741
            md=marshal.loads(__loader__.get_data('meta_data.mar'))
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   742
            project_version=md['project_version']
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   743
        except:
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   744
            pass
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   745
        env = os.environ
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   746
        K=env.keys()
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   747
        K.sort()
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   748
        store.update({  'gmt': time.asctime(time.gmtime(time.time())),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   749
                        'platform': sys.platform,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   750
                        'version': sys.version,
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   751
                        'hexversion': hex(sys.hexversion),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   752
                        'executable': sys.executable,
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   753
                        'exec_prefix': sys.exec_prefix,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   754
                        'prefix': sys.prefix,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   755
                        'path': sys.path,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   756
                        'argv': sys.argv,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   757
                        'cwd': cwd,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   758
                        'hostname': socket.gethostname(),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   759
                        'lcwd': lcwd,
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   760
                        'lpcwd': lpcwd,
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   761
                        'byteorder': sys.byteorder,
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   762
                        'maxint': sys.maxint,
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   763
                        'maxint': getattr(sys,'maxunicode','????'),
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   764
                        'api_version': getattr(sys,'api_version','????'),
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   765
                        'version_info': getattr(sys,'version_info','????'),
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   766
                        'winver': getattr(sys,'winver','????'),
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   767
                        'environment': '\n\t\t\t'.join(['']+['%s=%r' % (k,env[k]) for k in K]),
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   768
                        '__loader__': repr(__loader__),
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   769
                        'project_meta_data': md,
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   770
                        'project_version': project_version,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   771
                        })
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   772
        for M,A in (
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   773
                (sys,('getwindowsversion','getfilesystemencoding')),
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   774
                (os,('uname', 'ctermid', 'getgid', 'getuid', 'getegid',
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   775
                    'geteuid', 'getlogin', 'getgroups', 'getpgrp', 'getpid', 'getppid',
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   776
                    )),
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   777
                ):
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   778
            for a in A:
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   779
                if hasattr(M,a):
2300
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   780
                    try:
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   781
                        store[a] = getattr(M,a)()
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   782
                    except:
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   783
                        pass
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   784
        if exed!=cwd:
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   785
            try:
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   786
                store.update({'exed': exed, 'lexed': os.listdir(exed),})
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   787
            except:
3896af138a75 Attempt to robustify the memo
rgbecker
parents: 2297
diff changeset
   788
                pass
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   789
        if getScript:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   790
            fn = os.path.abspath(sys.argv[0])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   791
            if os.path.isfile(fn):
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   792
                try:
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   793
                    store['__script'] = (fn,open(fn,'r').read())
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   794
                except:
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   795
                    pass
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   796
        module_versions = {}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   797
        for n,m in sys.modules.items():
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   798
            if n=='reportlab' or n=='rlextra' or n[:10]=='reportlab.' or n[:8]=='rlextra.':
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   799
                v = [getattr(m,x,None) for x in ('__version__','__path__','__file__')]
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   800
                if filter(None,v):
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   801
                    v = [v[0]] + filter(None,v[1:])
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   802
                    module_versions[n] = tuple(v)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   803
        store['__module_versions'] = module_versions
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   804
        self.store['__payload'] = {}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   805
        self._add(kw)
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   806
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   807
    def _add(self,D):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   808
        payload = self.store['__payload']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   809
        for k, v in D.items():
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   810
            payload[k] = v
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   811
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   812
    def add(self,**kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   813
        self._add(kw)
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   814
2942
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   815
    def _dump(self,f):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   816
        import pickle
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   817
        try:
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   818
            pos=f.tell()
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   819
            pickle.dump(self.store,f)
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   820
        except:
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   821
            S=self.store.copy()
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   822
            ff=getStringIO()
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   823
            for k,v in S.iteritems():
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   824
                try:
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   825
                    pickle.dump({k:v},ff)
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   826
                except:
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   827
                    S[k] = '<unpicklable object %r>' % v
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   828
            f.seek(pos,0)
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   829
            pickle.dump(S,f)
2942
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   830
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   831
    def dump(self):
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   832
        f = open(self.fn,'wb')
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   833
        try:
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   834
            self._dump(f)
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   835
        finally:
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   836
            f.close()
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   837
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   838
    def dumps(self):
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   839
        f = getStringIO()
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   840
        self._dump(f)
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   841
        return f.getvalue()
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   842
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   843
    def _load(self,f):
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   844
        import pickle
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   845
        self.store = pickle.load(f)
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   846
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   847
    def load(self):
2942
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   848
        f = open(self.fn,'rb')
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   849
        try:
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   850
            self._load(f)
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   851
        finally:
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   852
            f.close()
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   853
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   854
    def loads(self,s):
e6e20484c315 reportlab/lib/utils.py: slight extensions to DebugMemo
rgbecker
parents: 2929
diff changeset
   855
        self._load(getStringIO(s))
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   856
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   857
    def _show_module_versions(self,k,v):
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   858
        self._writeln(k[2:])
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   859
        K = v.keys()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   860
        K.sort()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   861
        for k in K:
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   862
            vk = vk0 = v[k]
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   863
            if isinstance(vk,tuple): vk0 = vk[0]
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   864
            try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   865
                m = recursiveImport(k,sys.path[:],1)
3205
c65681e50856 utils.py: attempt to bring DebugMemo into line with nomt branch version
rgbecker
parents: 3180
diff changeset
   866
                d = getattr(m,'__version__',None)==vk0 and 'SAME' or 'DIFFERENT'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   867
            except:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   868
                m = None
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   869
                d = '??????unknown??????'
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   870
            self._writeln('  %s = %s (%s)' % (k,vk,d))
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   871
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   872
    def _banner(self,k,what):
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   873
        self._writeln('###################%s %s##################' % (what,k[2:]))
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   874
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   875
    def _start(self,k):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   876
        self._banner(k,'Start  ')
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   877
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   878
    def _finish(self,k):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   879
        self._banner(k,'Finish ')
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   880
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   881
    def _show_lines(self,k,v):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   882
        self._start(k)
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   883
        self._writeln(v)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   884
        self._finish(k)
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   885
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   886
    def _show_file(self,k,v):
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   887
        k = '%s %s' % (k,os.path.basename(v[0]))
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   888
        self._show_lines(k,v[1])
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   889
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   890
    def _show_payload(self,k,v):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   891
        if v:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   892
            import pprint
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   893
            self._start(k)
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   894
            pprint.pprint(v,self.stdout)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   895
            self._finish(k)
1538
faefcdc303a9 Added DebugMemo stuff
rgbecker
parents: 1537
diff changeset
   896
3122
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   897
    def _show_extensions(self):
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   898
        for mn in ('_rl_accel','_renderPM','sgmlop','pyRXP','pyRXPU','_imaging','Image'):
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   899
            try:
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   900
                A = [mn].append
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   901
                m = recursiveImport(mn,sys.path[:],1)
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   902
                A(m.__file__)
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   903
                for vn in ('__version__','VERSION','_version','version'):
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   904
                    if hasattr(m,vn):
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   905
                        A('%s=%r' % (vn,getattr(m,vn)))
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   906
            except:
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   907
                A('not found')
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   908
            self._writeln(' '+' '.join(A.__self__))
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   909
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   910
    specials = {'__module_versions': _show_module_versions,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   911
                '__payload': _show_payload,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   912
                '__traceback': _show_lines,
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   913
                '__script': _show_file,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   914
                }
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   915
    def show(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   916
        K = self.store.keys()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   917
        K.sort()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   918
        for k in K:
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   919
            if k not in self.specials.keys(): self._writeln('%-15s = %s' % (k,self.store[k]))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   920
        for k in K:
3122
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   921
            if k in self.specials.keys(): self.specials[k](self,k,self.store[k])
19218a7fd0e7 utils.py: add DebugMemo._show_extensions
rgbecker
parents: 3083
diff changeset
   922
        self._show_extensions()
1543
3681c7d8898d Slight formatting improvements & added payload method
rgbecker
parents: 1538
diff changeset
   923
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   924
    def payload(self,name):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   925
        return self.store['__payload'][name]
1561
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   926
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   927
    def __setitem__(self,name,value):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   928
        self.store['__payload'][name] = value
1561
1b10f25e76df Add DebugMemo __g/setitem__
rgbecker
parents: 1545
diff changeset
   929
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1650
diff changeset
   930
    def __getitem__(self,name):
1833
135322abc191 Fix recursivImport for case when baseDir is a sequence
rgbecker
parents: 1821
diff changeset
   931
        return self.store['__payload'][name]
2297
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   932
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   933
    def _writeln(self,msg):
7c706ac8a6b7 Added some more stuff and script name to DebugMemo output
rgbecker
parents: 2296
diff changeset
   934
        self.stdout.write(msg+'\n')
2365
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   935
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   936
def _flatten(L,a):
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   937
    for x in L:
2499
11bc8441ec51 legends.py: fix 2.1 compatibility problem
rgbecker
parents: 2497
diff changeset
   938
        if isSeqType(x): _flatten(x,a)
2365
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   939
        else: a(x)
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   940
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   941
def flatten(L):
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   942
    '''recursively flatten the list or tuple L'''
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   943
    R = []
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   944
    _flatten(L,R.append)
cda528e430aa reportlab/lib/utils.py: added flatten utility function
rgbecker
parents: 2356
diff changeset
   945
    return R
2406
311191cddb33 reportlab lib utils.py: add find_locals
rgbecker
parents: 2365
diff changeset
   946
311191cddb33 reportlab lib utils.py: add find_locals
rgbecker
parents: 2365
diff changeset
   947
def find_locals(func,depth=0):
311191cddb33 reportlab lib utils.py: add find_locals
rgbecker
parents: 2365
diff changeset
   948
    '''apply func to the locals at each stack frame till func returns a non false value'''
311191cddb33 reportlab lib utils.py: add find_locals
rgbecker
parents: 2365
diff changeset
   949
    while 1:
311191cddb33 reportlab lib utils.py: add find_locals
rgbecker
parents: 2365
diff changeset
   950
        _ = func(sys._getframe(depth).f_locals)
311191cddb33 reportlab lib utils.py: add find_locals
rgbecker
parents: 2365
diff changeset
   951
        if _: return _
311191cddb33 reportlab lib utils.py: add find_locals
rgbecker
parents: 2365
diff changeset
   952
        depth += 1
2454
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   953
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   954
class _FmtSelfDict:
2479
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   955
    def __init__(self,obj,overrideArgs):
2454
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   956
        self.obj = obj
2479
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   957
        self._overrideArgs = overrideArgs
2454
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   958
    def __getitem__(self,k):
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   959
        try:
2479
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   960
            return self._overrideArgs[k]
2454
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   961
        except KeyError:
2479
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   962
            try:
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   963
                return self.obj.__dict__[k]
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   964
            except KeyError:
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   965
                return getattr(self.obj,k)
2454
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   966
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   967
class FmtSelfDict:
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   968
    '''mixin to provide the _fmt method'''
2479
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   969
    def _fmt(self,fmt,**overrideArgs):
ea93388b723d Allow overriding parameters in _fmt utility method
jjlee
parents: 2459
diff changeset
   970
        D = _FmtSelfDict(self, overrideArgs)
2454
8cc3d50b0703 utils.py: added FmtSelfDict class
rgbecker
parents: 2448
diff changeset
   971
        return fmt % D
2715
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   972
2716
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   973
def _simpleSplit(txt,mW,SW):
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   974
    L = []
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   975
    ws = SW(' ')
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   976
    O = []
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   977
    w = -ws
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   978
    for t in txt.split():
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   979
        lt = SW(t)
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   980
        if w+ws+lt<=mW or O==[]:
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   981
            O.append(t)
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   982
            w = w + ws + lt
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   983
        else:
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   984
            L.append(' '.join(O))
2716
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   985
            O = [t]
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   986
            w = lt
3134
e403094e7c98 utils.py: removed old string usages
rgbecker
parents: 3122
diff changeset
   987
    if O!=[]: L.append(' '.join(O))
2716
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   988
    return L
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   989
2715
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   990
def simpleSplit(text,fontName,fontSize,maxWidth):
2716
6f35525eaffb reportlab/lib/utils.py: fix circular import
rgbecker
parents: 2715
diff changeset
   991
    from reportlab.pdfbase.pdfmetrics import stringWidth
2715
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   992
    lines = text.split('\n')
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   993
    SW = lambda text, fN=fontName, fS=fontSize: stringWidth(text, fN, fS)
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   994
    if maxWidth:
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   995
        L = []
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   996
        for l in lines:
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   997
            L[-1:-1] = _simpleSplit(l,maxWidth,SW)
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   998
        lines = L
5cdfb604dff2 reportlab/lib/utils.py: added simplSplit func
rgbecker
parents: 2706
diff changeset
   999
    return lines
2764
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1000
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1001
def escapeTextOnce(text):
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1002
    "Escapes once only"
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1003
    from xml.sax.saxutils import escape
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1004
    if text is None:
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1005
        return text
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1006
    text = escape(text)
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1007
    text = text.replace('&amp;amp;', '&amp;')
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1008
    text = text.replace('&amp;gt;', '&gt;')
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1009
    text = text.replace('&amp;lt;', '&lt;')
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1010
    return text
2858dec9bd27 added quote-once
andy
parents: 2720
diff changeset
  1011
2813
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1012
def fileName2Utf8(fn):
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1013
    '''attempt to convert a filename to utf8'''
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1014
    from reportlab.rl_config import fsEncodings
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1015
    for enc in fsEncodings:
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1016
        try:
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1017
            return fn.decode(enc).encode('utf8')
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1018
        except:
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1019
            pass
2b9091df4470 reportlab: add fsEncodings to rl_config, add fileName2Utf8
rgbecker
parents: 2794
diff changeset
  1020
    raise ValueError('cannot convert %r to utf8' % fn)
2929
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1021
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1022
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1023
import itertools
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1024
def prev_this_next(items):
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1025
    """
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1026
    Loop over a collection with look-ahead and look-back.
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1027
    
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1028
    From Thomas Guest, 
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1029
    http://wordaligned.org/articles/zippy-triples-served-with-python
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1030
    
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1031
    Seriously useful looping tool (Google "zippy triples")
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1032
    lets you loop a collection and see the previous and next items,
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1033
    which get set to None at the ends.
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1034
    
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1035
    To be used in layout algorithms where one wants a peek at the
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1036
    next item coming down the pipe.
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1037
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1038
    """
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1039
    
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1040
    extend = itertools.chain([None], items, [None])
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1041
    prev, this, next = itertools.tee(extend, 3)
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1042
    try:
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1043
        this.next()
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1044
        next.next()
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1045
        next.next()
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1046
    except StopIteration:
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1047
        pass
02a5623f4f26 added nifty triple iterator
andy
parents: 2902
diff changeset
  1048
    return itertools.izip(prev, this, next)
3171
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1049
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1050
def commasplit(s):
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1051
    '''
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1052
    Splits the string s at every unescaped comma and returns the result as a list.
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1053
    To escape a comma, double it. Individual items are stripped.
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1054
    To avoid the ambiguity of 3 successive commas to denote a comma at the beginning
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1055
    or end of an item, add a space between the item seperator and the escaped comma.
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1056
    
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1057
    >>> commasplit('a,b,c')
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1058
    ['a', 'b', 'c']
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1059
    >>> commasplit('a,, , b , c    ')
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1060
    ['a,', 'b', 'c']
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1061
    >>> commasplit('a, ,,b, c')
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1062
    ['a', ',b', 'c']
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1063
    '''
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1064
    n = len(s)-1
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1065
    s += ' '
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1066
    i = 0
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1067
    r=['']
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1068
    while i<=n:
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1069
        if s[i]==',':
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1070
            if s[i+1]==',':
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1071
                r[-1]+=','
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1072
                i += 1
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1073
            else:
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1074
                r[-1] = r[-1].strip()
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1075
                if i!=n: r.append('')
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1076
        else:
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1077
            r[-1] += s[i]
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1078
        i+=1
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1079
    r[-1] = r[-1].strip()
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1080
    return r
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1081
    
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1082
def commajoin(l):
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1083
    '''
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1084
    Inverse of commasplit, except that whitespace around items is not conserved.
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1085
    Adds more whitespace than needed for simplicity and performance.
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1086
    
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1087
    >>> commasplit(commajoin(['a', 'b', 'c']))
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1088
    ['a', 'b', 'c']
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1089
    >>> commasplit((commajoin(['a,', ' b ', 'c']))
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1090
    ['a,', 'b', 'c']
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1091
    >>> commasplit((commajoin(['a ', ',b', 'c']))
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1092
    ['a', ',b', 'c']    
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1093
    '''
c94c900d9263 Better syntax for listing indexing terms inside an index paragraph tag attribute.
jonas
parents: 3134
diff changeset
  1094
    return ','.join([ ' ' + i.replace(',', ',,') + ' ' for i in l ])
3213
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1095
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1096
def findInPaths(fn,paths,isfile=True,fail=False):
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1097
    '''search for relative files in likely places'''
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1098
    exists = isfile and os.path.isfile or os.path.isdir
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1099
    if exists(fn): return fn
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1100
    pjoin = os.path.join
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1101
    if not os.path.isabs(fn):
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1102
        for p in paths:
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1103
            pfn = pjoin(p,fn)
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1104
            if exists(pfn):
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1105
                return pfn
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1106
    if fail: raise ValueError('cannot locate %r with paths=%r' % (fn,paths))
b6da4a7ffec2 utils.py: add findInPaths
rgbecker
parents: 3205
diff changeset
  1107
    return fn
3253
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1108
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1109
def annotateException(msg,enc='utf8'):
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1110
    '''add msg to the args of an existing exception'''
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1111
    t,v,b=sys.exc_info()
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1112
    e = -1
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1113
    A = list(v.args)
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1114
    for i,a in enumerate(A):
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1115
        if isinstance(a,basestring):
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1116
            e = i
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1117
            break
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1118
    if e>=0:
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1119
        if isinstance(a,unicode):
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1120
            if not isinstance(msg,unicode):
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1121
                msg=msg.decode(enc)
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1122
        else:
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1123
            if isinstance(msg,unicode):
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1124
                msg=msg.encode(enc)
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1125
            else:
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1126
                msg = str(msg)
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1127
        A[e] += msg
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1128
    else:
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1129
        A.append(msg)
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1130
    v.args = tuple(A)
06194e4167b9 reportlab/lib/utils.py: add annotateException
rgbecker
parents: 3213
diff changeset
  1131
    raise t,v,b