summaryrefslogtreecommitdiff
path: root/bin/linecount.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/linecount.py')
-rw-r--r--bin/linecount.py123
1 files changed, 123 insertions, 0 deletions
diff --git a/bin/linecount.py b/bin/linecount.py
new file mode 100644
index 0000000..359f642
--- /dev/null
+++ b/bin/linecount.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+#
+# 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__ = "bin/linecount.py 4577 2009/12/27 19:44:43 scons"
+
+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())
+ )