ยปCore Development>Code coverage>Tools/scripts/byext.py

Python code coverage for Tools/scripts/byext.py

#countcontent
1n/a#! /usr/bin/env python3
2n/a
3n/a"""Show file statistics by extension."""
4n/a
5n/aimport os
6n/aimport sys
7n/a
8n/a
9n/aclass Stats:
10n/a
11n/a def __init__(self):
12n/a self.stats = {}
13n/a
14n/a def statargs(self, args):
15n/a for arg in args:
16n/a if os.path.isdir(arg):
17n/a self.statdir(arg)
18n/a elif os.path.isfile(arg):
19n/a self.statfile(arg)
20n/a else:
21n/a sys.stderr.write("Can't find %s\n" % arg)
22n/a self.addstats("<???>", "unknown", 1)
23n/a
24n/a def statdir(self, dir):
25n/a self.addstats("<dir>", "dirs", 1)
26n/a try:
27n/a names = os.listdir(dir)
28n/a except OSError as err:
29n/a sys.stderr.write("Can't list %s: %s\n" % (dir, err))
30n/a self.addstats("<dir>", "unlistable", 1)
31n/a return
32n/a for name in sorted(names):
33n/a if name.startswith(".#"):
34n/a continue # Skip CVS temp files
35n/a if name.endswith("~"):
36n/a continue # Skip Emacs backup files
37n/a full = os.path.join(dir, name)
38n/a if os.path.islink(full):
39n/a self.addstats("<lnk>", "links", 1)
40n/a elif os.path.isdir(full):
41n/a self.statdir(full)
42n/a else:
43n/a self.statfile(full)
44n/a
45n/a def statfile(self, filename):
46n/a head, ext = os.path.splitext(filename)
47n/a head, base = os.path.split(filename)
48n/a if ext == base:
49n/a ext = "" # E.g. .cvsignore is deemed not to have an extension
50n/a ext = os.path.normcase(ext)
51n/a if not ext:
52n/a ext = "<none>"
53n/a self.addstats(ext, "files", 1)
54n/a try:
55n/a with open(filename, "rb") as f:
56n/a data = f.read()
57n/a except IOError as err:
58n/a sys.stderr.write("Can't open %s: %s\n" % (filename, err))
59n/a self.addstats(ext, "unopenable", 1)
60n/a return
61n/a self.addstats(ext, "bytes", len(data))
62n/a if b'\0' in data:
63n/a self.addstats(ext, "binary", 1)
64n/a return
65n/a if not data:
66n/a self.addstats(ext, "empty", 1)
67n/a # self.addstats(ext, "chars", len(data))
68n/a lines = str(data, "latin-1").splitlines()
69n/a self.addstats(ext, "lines", len(lines))
70n/a del lines
71n/a words = data.split()
72n/a self.addstats(ext, "words", len(words))
73n/a
74n/a def addstats(self, ext, key, n):
75n/a d = self.stats.setdefault(ext, {})
76n/a d[key] = d.get(key, 0) + n
77n/a
78n/a def report(self):
79n/a exts = sorted(self.stats)
80n/a # Get the column keys
81n/a columns = {}
82n/a for ext in exts:
83n/a columns.update(self.stats[ext])
84n/a cols = sorted(columns)
85n/a colwidth = {}
86n/a colwidth["ext"] = max([len(ext) for ext in exts])
87n/a minwidth = 6
88n/a self.stats["TOTAL"] = {}
89n/a for col in cols:
90n/a total = 0
91n/a cw = max(minwidth, len(col))
92n/a for ext in exts:
93n/a value = self.stats[ext].get(col)
94n/a if value is None:
95n/a w = 0
96n/a else:
97n/a w = len("%d" % value)
98n/a total += value
99n/a cw = max(cw, w)
100n/a cw = max(cw, len(str(total)))
101n/a colwidth[col] = cw
102n/a self.stats["TOTAL"][col] = total
103n/a exts.append("TOTAL")
104n/a for ext in exts:
105n/a self.stats[ext]["ext"] = ext
106n/a cols.insert(0, "ext")
107n/a
108n/a def printheader():
109n/a for col in cols:
110n/a print("%*s" % (colwidth[col], col), end=' ')
111n/a print()
112n/a
113n/a printheader()
114n/a for ext in exts:
115n/a for col in cols:
116n/a value = self.stats[ext].get(col, "")
117n/a print("%*s" % (colwidth[col], value), end=' ')
118n/a print()
119n/a printheader() # Another header at the bottom
120n/a
121n/a
122n/adef main():
123n/a args = sys.argv[1:]
124n/a if not args:
125n/a args = [os.curdir]
126n/a s = Stats()
127n/a s.statargs(args)
128n/a s.report()
129n/a
130n/a
131n/aif __name__ == "__main__":
132n/a main()