Merge pull request #4524 from mwichmann/maint/py-versions
[scons.git] / src / test_strings.py
blob958cb1501b4217ffc8c585b14d59617a93eafd0e
1 #!/usr/bin/env python
3 # __COPYRIGHT__
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26 """
27 Verify that we have proper strings like Copyright notices on all the
28 right files in our distributions.
30 Note that this is a source file and packaging test, not a functional test,
31 so the name of this script doesn't end in *Tests.py.
32 """
34 import fnmatch
35 import os
36 import os.path
37 import re
39 import TestCmd
40 import TestSCons
42 # Use TestCmd, not TestSCons, so we don't chdir to a temporary directory.
43 test = TestCmd.TestCmd()
45 scons_version = TestSCons.SConsVersion
47 def build_path(*args):
48 return os.path.join('build', *args)
50 build_scons = build_path('scons')
51 build_local = build_path('scons-local', 'scons-local-'+scons_version)
52 build_src = build_path('scons-src')
54 class Checker:
55 def __init__(self, directory,
56 search_list = [],
57 remove_list = [],
58 remove_patterns = []):
59 self.directory = directory
60 self.search_list = search_list
61 self.remove_dict = {}
62 for r in remove_list:
63 self.remove_dict[os.path.join(directory, r)] = 1
64 self.remove_patterns = remove_patterns
66 def directory_exists(self):
67 return os.path.exists(self.directory)
69 def remove_this(self, name, path):
70 if self.remove_dict.get(path):
71 return 1
72 else:
73 for pattern in self.remove_patterns:
74 if fnmatch.fnmatch(name, pattern):
75 return 1
76 return 0
78 def search_this(self, path):
79 if self.search_list:
80 for pattern in self.search_list:
81 if fnmatch.fnmatch(path, pattern):
82 return 1
83 return None
84 else:
85 return os.path.isfile(path)
87 def find_missing(self):
88 result = []
89 for dirpath, dirnames, filenames in os.walk(self.directory):
90 if '.svn' in dirnames:
91 dirnames.remove('.svn')
92 for dname in dirnames[:]:
93 dpath = os.path.join(dirpath, dname)
94 if self.remove_this(dname, dpath):
95 dirnames.remove(dname)
96 for fname in filenames:
97 fpath = os.path.join(dirpath, fname)
98 if self.search_this(fpath) and not self.remove_this(fname, fpath):
99 with open(fpath, 'r') as f:
100 body = f.read()
101 for expr in self.expressions:
102 if not expr.search(body):
103 msg = '%s: missing %s' % (fpath, repr(expr.pattern))
104 result.append(msg)
105 return result
107 class CheckUnexpandedStrings(Checker):
108 expressions = [
109 re.compile('__COPYRIGHT__'),
110 re.compile('__FILE__ __REVISION__ __DATE__ __DEVELOPER__'),
112 def must_be_built(self):
113 return None
115 class CheckPassTest(Checker):
116 expressions = [
117 re.compile(r'\.pass_test()'),
119 def must_be_built(self):
120 return None
122 class CheckExpandedCopyright(Checker):
123 expressions = [
124 re.compile('Copyright.*The SCons Foundation'),
126 def must_be_built(self):
127 return 1
129 check_list = [
131 CheckUnexpandedStrings(
132 'src',
133 search_list = [ '*.py' ],
134 remove_list = [
135 'engine/SCons/compat/_scons_sets.py',
136 'engine/SCons/compat/_scons_subprocess.py',
137 'engine/SCons/Conftest.py',
138 'engine/SCons/dblite.py',
142 CheckUnexpandedStrings(
143 'test',
144 search_list = [ '*.py' ],
147 CheckPassTest(
148 'test',
149 search_list = [ '*.py' ],
150 remove_list = [
151 'Fortran/common.py',
155 CheckExpandedCopyright(
156 build_scons,
157 remove_list = [
158 'build',
159 'build-stamp',
160 'configure-stamp',
161 'debian',
162 'dist',
163 'gentoo',
164 'engine/SCons/compat/_scons_sets.py',
165 'engine/SCons/compat/_scons_subprocess.py',
166 'engine/SCons/Conftest.py',
167 'engine/SCons/dblite.py',
168 'MANIFEST',
169 'setup.cfg',
171 # We run epydoc on the *.py files, which generates *.pyc files.
172 remove_patterns = [
173 '*.pyc',
177 CheckExpandedCopyright(
178 build_local,
179 remove_list = [
180 'SCons/compat/_scons_sets.py',
181 'SCons/compat/_scons_subprocess.py',
182 'SCons/Conftest.py',
183 'SCons/dblite.py',
184 'scons-%s.egg-info' % scons_version,
188 CheckExpandedCopyright(
189 build_src,
190 remove_list = [
191 'bench/timeit.py',
192 'bin',
193 'config',
194 'debian',
195 'gentoo',
196 'doc/design',
197 'doc/MANIFEST',
198 'doc/python10',
199 'doc/reference',
200 'doc/developer/MANIFEST',
201 'doc/man/MANIFEST',
202 'doc/user/cons.pl',
203 'doc/user/MANIFEST',
204 'doc/user/SCons-win32-install-1.jpg',
205 'doc/user/SCons-win32-install-2.jpg',
206 'doc/user/SCons-win32-install-3.jpg',
207 'doc/user/SCons-win32-install-4.jpg',
208 'examples',
209 'gentoo',
210 'testing/framework/TestCmd.py',
211 'testing/framework/TestCmdTests.py',
212 'testing/framework/TestCommon.py',
213 'testing/framework/TestCommonTests.py',
214 'src/MANIFEST.in',
215 'src/setup.cfg',
216 'src/engine/MANIFEST.in',
217 'src/engine/MANIFEST-xml.in',
218 'src/engine/setup.cfg',
219 'src/engine/SCons/compat/_scons_sets.py',
220 'src/engine/SCons/compat/_scons_subprocess.py',
221 'src/engine/SCons/Conftest.py',
222 'src/engine/SCons/dblite.py',
223 'src/script/MANIFEST.in',
224 'src/script/setup.cfg',
225 'test/Fortran/.exclude_tests',
226 'timings/changelog.html',
227 'timings/ElectricCloud/genscons.pl',
228 'timings/graph.html',
229 'timings/index.html',
230 'review.py',
232 remove_patterns = [
233 '*.js',
239 missing_strings = []
240 not_built = []
242 for collector in check_list:
243 if collector.directory_exists():
244 missing_strings.extend(collector.find_missing())
245 elif collector.must_be_built():
246 not_built.append(collector.directory)
248 if missing_strings:
249 print("Found the following files with missing strings:")
250 print("\t" + "\n\t".join(missing_strings))
251 test.fail_test(1)
253 if not_built:
254 print("Cannot check all strings, the following have apparently not been built:")
255 print("\t" + "\n\t".join(not_built))
256 test.no_result(1)
258 test.pass_test()
260 # Local Variables:
261 # tab-width:4
262 # indent-tabs-mode:nil
263 # End:
264 # vim: set expandtab tabstop=4 shiftwidth=4: