src/reportlab/lib/testutils.py
author rgbecker
Mon, 15 Sep 2008 11:16:32 +0000
changeset 2986 89edcdd280a7
child 2988 1540a4be3b99
permissions -rw-r--r--
tests.utils --> reportlab.lib.testutils
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2986
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2008
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     2
#see license.txt for license details
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     3
"""Utilities for testing Python packages.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     4
"""
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     5
__version__='''$Id$'''
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     6
import sys, os, string, fnmatch, copy, re
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     7
from ConfigParser import ConfigParser
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     8
import unittest
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
     9
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    10
# Helper functions.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    11
def isWritable(D):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    12
    try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    13
        fn = '00DELETE.ME'
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    14
        f = open(fn, 'w')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    15
        f.write('test of writability - can be deleted')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    16
        f.close()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    17
        if os.path.isfile(fn):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    18
            os.remove(fn)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    19
            return 1
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    20
    except:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    21
        return 0
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    22
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    23
_OUTDIR = None
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    24
def setOutDir(name):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    25
    """Is it a writable file system distro being invoked within
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    26
    test directory?  If so, can write test output here.  If not,
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    27
    it had better go in a temp directory.  Only do this once per
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    28
    process"""
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    29
    global _OUTDIR
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    30
    if _OUTDIR: return _OUTDIR
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    31
    D = [d[9:] for d in sys.argv if d.startswith('--outdir=')]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    32
    if D:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    33
        _OUTDIR = D[-1]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    34
        try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    35
            os.makedirs(_OUTDIR)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    36
        except:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    37
            pass
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    38
        map(sys.argv.remove,D)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    39
    else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    40
        assert name=='__main__',"setOutDir should only be called in the main script"
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    41
        scriptDir=os.path.dirname(sys.argv[0])
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    42
        if not scriptDir: scriptDir=os.getcwd()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    43
        _OUTDIR = scriptDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    44
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    45
    if not isWritable(_OUTDIR):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    46
        _OUTDIR = get_rl_tempdir('reportlab_test')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    47
    return _OUTDIR
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    48
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    49
def outputfile(fn):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    50
    """This works out where to write test output.  If running
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    51
    code in a locked down file system, this will be a
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    52
    temp directory; otherwise, the output of 'test_foo.py' will
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    53
    normally be a file called 'test_foo.pdf', next door.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    54
    """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    55
    D = setOutDir(__name__)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    56
    if fn: D = os.path.join(D,fn)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    57
    return D
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    58
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    59
def printLocation(depth=1):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    60
    if sys._getframe(depth).f_locals.get('__name__')=='__main__':
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    61
        outDir = outputfile('')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    62
        if outDir!=_OUTDIR:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    63
            print 'Logs and output files written to folder "%s"' % outDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    64
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    65
def makeSuiteForClasses(*classes):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    66
    "Return a test suite with tests loaded from provided classes."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    67
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    68
    suite = unittest.TestSuite()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    69
    loader = unittest.TestLoader()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    70
    for C in classes:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    71
        suite.addTest(loader.loadTestsFromTestCase(C))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    72
    return suite
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    73
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    74
def getCVSEntries(folder, files=1, folders=0):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    75
    """Returns a list of filenames as listed in the CVS/Entries file.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    76
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    77
    'folder' is the folder that should contain the CVS subfolder.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    78
    If there is no such subfolder an empty list is returned.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    79
    'files' is a boolean; 1 and 0 means to return files or not.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    80
    'folders' is a boolean; 1 and 0 means to return folders or not.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    81
    """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    82
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    83
    join = os.path.join
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    84
    split = string.split
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    85
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    86
    # If CVS subfolder doesn't exist return empty list.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    87
    try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    88
        f = open(join(folder, 'CVS', 'Entries'))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    89
    except IOError:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    90
        return []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    91
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    92
    # Return names of files and/or folders in CVS/Entries files.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    93
    allEntries = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    94
    for line in f.readlines():
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    95
        if folders and line[0] == 'D' \
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    96
           or files and line[0] != 'D':
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    97
            entry = split(line, '/')[1]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    98
            if entry:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
    99
                allEntries.append(join(folder, entry))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   100
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   101
    return allEntries
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   102
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   103
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   104
# Still experimental class extending ConfigParser's behaviour.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   105
class ExtConfigParser(ConfigParser):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   106
    "A slightly extended version to return lists of strings."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   107
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   108
    pat = re.compile('\s*\[.*\]\s*')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   109
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   110
    def getstringlist(self, section, option):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   111
        "Coerce option to a list of strings or return unchanged if that fails."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   112
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   113
        value = apply(ConfigParser.get, (self, section, option))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   114
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   115
        # This seems to allow for newlines inside values
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   116
        # of the config file, but be careful!!
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   117
        val = string.replace(value, '\n', '')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   118
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   119
        if self.pat.match(val):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   120
            return eval(val)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   121
        else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   122
            return value
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   123
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   124
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   125
# This class as suggested by /F with an additional hook
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   126
# to be able to filter filenames.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   127
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   128
class GlobDirectoryWalker:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   129
    "A forward iterator that traverses files in a directory tree."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   130
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   131
    def __init__(self, directory, pattern='*'):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   132
        self.index = 0
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   133
        self.pattern = pattern
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   134
        directory.replace('/',os.sep)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   135
        if os.path.isdir(directory):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   136
            self.stack = [directory]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   137
            self.files = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   138
        else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   139
            from reportlab.lib.utils import isCompactDistro, __loader__, rl_isdir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   140
            if not isCompactDistro() or not __loader__ or not rl_isdir(directory):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   141
                raise ValueError('"%s" is not a directory' % directory)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   142
            self.directory = directory[len(__loader__.archive)+len(os.sep):]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   143
            pfx = self.directory+os.sep
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   144
            n = len(pfx)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   145
            self.files = map(lambda x, n=n: x[n:],filter(lambda x,pfx=pfx: x.startswith(pfx),__loader__._files.keys()))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   146
            self.stack = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   147
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   148
    def __getitem__(self, index):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   149
        while 1:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   150
            try:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   151
                file = self.files[self.index]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   152
                self.index = self.index + 1
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   153
            except IndexError:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   154
                # pop next directory from stack
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   155
                self.directory = self.stack.pop()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   156
                self.files = os.listdir(self.directory)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   157
                # now call the hook
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   158
                self.files = self.filterFiles(self.directory, self.files)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   159
                self.index = 0
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   160
            else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   161
                # got a filename
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   162
                fullname = os.path.join(self.directory, file)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   163
                if os.path.isdir(fullname) and not os.path.islink(fullname):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   164
                    self.stack.append(fullname)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   165
                if fnmatch.fnmatch(file, self.pattern):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   166
                    return fullname
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   167
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   168
    def filterFiles(self, folder, files):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   169
        "Filter hook, overwrite in subclasses as needed."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   170
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   171
        return files
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   172
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   173
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   174
class RestrictedGlobDirectoryWalker(GlobDirectoryWalker):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   175
    "An restricted directory tree iterator."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   176
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   177
    def __init__(self, directory, pattern='*', ignore=None):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   178
        apply(GlobDirectoryWalker.__init__, (self, directory, pattern))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   179
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   180
        if ignore == None:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   181
            ignore = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   182
        self.ignoredPatterns = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   183
        if type(ignore) == type([]):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   184
            for p in ignore:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   185
                self.ignoredPatterns.append(p)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   186
        elif type(ignore) == type(''):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   187
            self.ignoredPatterns.append(ignore)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   188
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   189
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   190
    def filterFiles(self, folder, files):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   191
        "Filters all items from files matching patterns to ignore."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   192
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   193
        indicesToDelete = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   194
        for i in xrange(len(files)):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   195
            f = files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   196
            for p in self.ignoredPatterns:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   197
                if fnmatch.fnmatch(f, p):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   198
                    indicesToDelete.append(i)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   199
        indicesToDelete.reverse()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   200
        for i in indicesToDelete:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   201
            del files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   202
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   203
        return files
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   204
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   205
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   206
class CVSGlobDirectoryWalker(GlobDirectoryWalker):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   207
    "An directory tree iterator that checks for CVS data."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   208
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   209
    def filterFiles(self, folder, files):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   210
        """Filters files not listed in CVS subfolder.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   211
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   212
        This will look in the CVS subfolder of 'folder' for
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   213
        a file named 'Entries' and filter all elements from
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   214
        the 'files' list that are not listed in 'Entries'.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   215
        """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   216
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   217
        join = os.path.join
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   218
        cvsFiles = getCVSEntries(folder)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   219
        if cvsFiles:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   220
            indicesToDelete = []
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   221
            for i in xrange(len(files)):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   222
                f = files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   223
                if join(folder, f) not in cvsFiles:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   224
                    indicesToDelete.append(i)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   225
            indicesToDelete.reverse()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   226
            for i in indicesToDelete:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   227
                del files[i]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   228
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   229
        return files
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   230
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   231
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   232
# An experimental untested base class with additional 'security'.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   233
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   234
class SecureTestCase(unittest.TestCase):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   235
    """Secure testing base class with additional pre- and postconditions.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   236
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   237
    We try to ensure that each test leaves the environment it has
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   238
    found unchanged after the test is performed, successful or not.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   239
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   240
    Currently we restore sys.path and the working directory, but more
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   241
    of this could be added easily, like removing temporary files or
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   242
    similar things.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   243
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   244
    Use this as a base class replacing unittest.TestCase and call
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   245
    these methods in subclassed versions before doing your own
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   246
    business!
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   247
    """
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   248
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   249
    def setUp(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   250
        "Remember sys.path and current working directory."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   251
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   252
        self._initialPath = copy.copy(sys.path)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   253
        self._initialWorkDir = os.getcwd()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   254
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   255
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   256
    def tearDown(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   257
        "Restore previous sys.path and working directory."
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   258
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   259
        sys.path = self._initialPath
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   260
        os.chdir(self._initialWorkDir)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   261
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   262
class NearTestCase(unittest.TestCase):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   263
    def assertNear(a,b,accuracy=1e-5):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   264
        if isinstance(a,(float,int)):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   265
            if abs(a-b)>accuracy:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   266
                raise AssertionError("%s not near %s" % (a, b))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   267
        else:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   268
            for ae,be in zip(a,b):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   269
                if abs(ae-be)>accuracy:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   270
                    raise AssertionError("%s not near %s" % (a, b))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   271
    assertNear = staticmethod(assertNear)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   272
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   273
class ScriptThatMakesFileTest(unittest.TestCase):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   274
    """Runs a Python script at OS level, expecting it to produce a file.
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   275
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   276
    It CDs to the working directory to run the script."""
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   277
    def __init__(self, scriptDir, scriptName, outFileName, verbose=0):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   278
        self.scriptDir = scriptDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   279
        self.scriptName = scriptName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   280
        self.outFileName = outFileName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   281
        self.verbose = verbose
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   282
        # normally, each instance is told which method to run)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   283
        unittest.TestCase.__init__(self)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   284
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   285
    def setUp(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   286
        self.cwd = os.getcwd()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   287
        from tests.utils import testsFolder
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   288
        scriptDir=self.scriptDir
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   289
        if not os.path.isabs(scriptDir):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   290
            scriptDir=os.path.join(testsFolder,scriptDir)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   291
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   292
        os.chdir(scriptDir)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   293
        assert os.path.isfile(self.scriptName), "Script %s not found!" % self.scriptName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   294
        if os.path.isfile(self.outFileName):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   295
            os.remove(self.outFileName)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   296
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   297
    def tearDown(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   298
        os.chdir(self.cwd)
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   299
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   300
    def runTest(self):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   301
        fmt = sys.platform=='win32' and '"%s" %s' or '%s %s'
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   302
        p = os.popen(fmt % (sys.executable,self.scriptName),'r')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   303
        out = p.read()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   304
        if self.verbose:
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   305
            print out
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   306
        status = p.close()
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   307
        assert os.path.isfile(self.outFileName), "File %s not created!" % self.outFileName
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   308
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   309
import tests as testsFolder
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   310
testsFolder=testsFolder.__path__[0]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   311
if not os.path.isabs(testsFolder): testsFolder=os.path.normpath(os.path.abspath(testsFolder))
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   312
RL_HOME=os.path.join(testsFolder,'src','reportlab')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   313
if not os.path.isdir(RL_HOME):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   314
    RL_HOME=os.path.join(testsFolder,'reportlab')
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   315
if not os.path.isdir(RL_HOME):
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   316
    import reportlab as RL_HOME
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   317
    RL_HOME=RL_HOME.__path__[0]
89edcdd280a7 tests.utils --> reportlab.lib.testutils
rgbecker
parents:
diff changeset
   318
    if not os.path.isabs(RL_HOME): RL_HOME=os.path.normpath(os.path.abspath(RL_HOME))