From: stevenknight Date: Wed, 13 May 2009 04:01:13 +0000 (+0000) Subject: Rename bin/linecount to bin/linecount.py and provide finer-grained X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=92a0844de84779916953f7773b3ba403ccb20d3d;p=scons.git Rename bin/linecount to bin/linecount.py and provide finer-grained (and more accurate) breakdowns of the tests. git-svn-id: http://scons.tigris.org/svn/scons/trunk@4193 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/bin/linecount b/bin/linecount deleted file mode 100644 index 7ab37f58..00000000 --- a/bin/linecount +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Count statistics about SCons test and source files. This must be run -# against a fully-populated tree (for example, one that's been freshly -# checked out). -# -# A test file is anything under the src/ directory that begins with -# 'test_' or ends in 'Tests.py', or anything under the test/ directory -# that ends in '.py'. Note that runtest.py script does *not*, by default, -# consider the files that begin with 'test_' to be tests, because they're -# tests of SCons packaging and installation, not functional tests of -# SCons code. -# -# A source file is anything under the src/engine/ or src/script/ -# directories that ends in '.py' but does NOT begin with 'test_' -# or end in 'Tests.py'. -# -# We report the number of tests and sources, the total number of lines -# in each category, the number of non-blank lines, and the number of -# non-comment lines. The last figure (non-comment) lines is the most -# interesting one for most purposes. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os.path -import string - -tests = [] -sources = [] - -def is_test(x): - return x[:5] == 'test_' or x[-8:] == 'Tests.py' -def is_python(x): - return x[-3:] == '.py' - -def t(arg, dirname, names): - names = filter(is_test, names) - arg.extend(map(lambda n, d=dirname: os.path.join(d, n), names)) -os.path.walk('src', t, tests) - -def p(arg, dirname, names): - names = filter(is_python, names) - arg.extend(map(lambda n, d=dirname: os.path.join(d, n), names)) -os.path.walk('test', p, tests) - -def s(arg, dirname, names): - names = filter(lambda n: is_python(n) and not is_test(n), names) - arg.extend(map(lambda n, d=dirname: os.path.join(d, n), names)) -os.path.walk('src/engine', s, sources) -os.path.walk('src/script', s, sources) - -def gather(files): - lines = [] - for file in files: - lines.extend(open(file).readlines()) - return lines - -tlines = map(string.lstrip, gather(tests)) -slines = map(string.lstrip, gather(sources)) - -nbtl = filter(lambda x: x != '', tlines) -nbsl = filter(lambda x: x != '', slines) - -nctl = filter(lambda x: x[0] != '#', nbtl) -ncsl = filter(lambda x: x[0] != '#', nbsl) - -def ratio(over, under): - return "%.2f" % (float(len(over)) / float(len(under))) - -rfiles = ratio(tests, sources) -rlines = ratio(tlines, slines) -rnonblank = ratio(nbtl, nbsl) -rnoncomment = ratio(nctl, ncsl) - -fmt = "%-8s %12s %12s %12s %12s" - -print fmt % ('', 'files', 'lines', 'non-blank', 'non-comment') -print fmt % ('tests:', len(tests), len(tlines), len(nbtl), len(nctl)) -print fmt % ('sources:', len(sources), len(slines), len(nbsl), len(ncsl)) -print fmt % ('ratio:', rfiles, rlines, rnonblank, rnoncomment) diff --git a/bin/linecount.py b/bin/linecount.py new file mode 100644 index 00000000..33f9f737 --- /dev/null +++ b/bin/linecount.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Count statistics about SCons test and source files. This must be run +# against a fully-populated tree (for example, one that's been freshly +# checked out). +# +# A test file is anything under the src/ directory that begins with +# 'test_' or ends in 'Tests.py', or anything under the test/ directory +# that ends in '.py'. Note that runtest.py script does *not*, by default, +# consider the files that begin with 'test_' to be tests, because they're +# tests of SCons packaging and installation, not functional tests of +# SCons code. +# +# A source file is anything under the src/engine/ or src/script/ +# directories that ends in '.py' but does NOT begin with 'test_' +# or end in 'Tests.py'. +# +# We report the number of tests and sources, the total number of lines +# in each category, the number of non-blank lines, and the number of +# non-comment lines. The last figure (non-comment) lines is the most +# interesting one for most purposes. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os.path +import string + +fmt = "%-16s %5s %7s %9s %11s %11s" + +class Collection(object): + def __init__(self, name, files=None, pred=None): + self._name = name + if files is None: + files = [] + self.files = files + if pred is None: + pred = lambda x: True + self.pred = pred + def __call__(self, fname): + return self.pred(fname) + def __len__(self): + return len(self.files) + def extend(self, files): + self.files.extend(files) + def lines(self): + try: + return self._lines + except AttributeError: + self._lines = lines = [] + for file in self.files: + file_lines = open(file).readlines() + lines.extend([s.lstrip() for s in file_lines]) + return lines + def non_blank(self): + return [s for s in self.lines() if s != ''] + def non_comment(self): + return [s for s in self.lines() if s == '' or s[0] != '#'] + def non_blank_non_comment(self): + return [s for s in self.lines() if s != '' and s[0] != '#'] + def printables(self): + return (self._name + ':', + len(self.files), + len(self.lines()), + len(self.non_blank()), + len(self.non_comment()), + len(self.non_blank_non_comment())) + +def is_Tests_py(x): + return x[-8:] == 'Tests.py' +def is_test_(x): + return x[:5] == 'test_' +def is_python(x): + return x[-3:] == '.py' +def is_source(x): + return is_python(x) and not is_Tests_py(x) and not is_test_(x) + +src_Tests_py_tests = Collection('src/ *Tests.py', pred=is_Tests_py) +src_test_tests = Collection('src/ test_*.py', pred=is_test_) +test_tests = Collection('test/ tests', pred=is_python) +sources = Collection('sources', pred=is_source) + +def t(arg, dirname, names): + try: names.remove('.svn') + except ValueError: pass + names = filter(arg, names) + arg.extend(map(lambda n, d=dirname: os.path.join(d, n), names)) + +os.path.walk('src', t, src_Tests_py_tests) +os.path.walk('src', t, src_test_tests) +os.path.walk('test', t, test_tests) +os.path.walk('src/engine', t, sources) +os.path.walk('src/script', t, sources) + +src_tests = Collection('src/ tests', src_Tests_py_tests.files + + src_test_tests.files) +all_tests = Collection('all tests', src_tests.files + test_tests.files) + +def ratio(over, under): + return "%.2f" % (float(len(over)) / float(len(under))) + +print fmt % ('', '', '', '', '', 'non-blank') +print fmt % ('', 'files', 'lines', 'non-blank', 'non-comment', 'non-comment') +print +print fmt % src_Tests_py_tests.printables() +print fmt % src_test_tests.printables() +print +print fmt % src_tests.printables() +print fmt % test_tests.printables() +print +print fmt % all_tests.printables() +print fmt % sources.printables() +print +print fmt % ('ratio:', + ratio(all_tests, sources), + ratio(all_tests.lines(), sources.lines()), + ratio(all_tests.non_blank(), sources.non_blank()), + ratio(all_tests.non_comment(), sources.non_comment()), + ratio(all_tests.non_blank_non_comment(), + sources.non_blank_non_comment()) + )