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