Rename bin/linecount to bin/linecount.py and provide finer-grained
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 13 May 2009 04:01:13 +0000 (04:01 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 13 May 2009 04:01:13 +0000 (04:01 +0000)
(and more accurate) breakdowns of the tests.

git-svn-id: http://scons.tigris.org/svn/scons/trunk@4193 fdb21ef1-2011-0410-befe-b5e4ea1792b1

bin/linecount [deleted file]
bin/linecount.py [new file with mode: 0644]

diff --git a/bin/linecount b/bin/linecount
deleted file mode 100644 (file)
index 7ab37f5..0000000
+++ /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 (file)
index 0000000..33f9f73
--- /dev/null
@@ -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())
+            )