Files
troupe-standup/wizard-work/ledger/extract_extension_census.py
T

97 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""Extract a ranked file-extension census from wizard-work/ledger/repo_files.tsv.
Source: repo_files.tsv is a (rank, path) inventory of the troupe worktree:
rank<TAB>path
Some path cells were written through a Python repr/json serializer and carry
escaped quotes/newlines; we de-escape, take the basename, and count
extensions (lowercased, leading dot on the suffix unless there is none,
which is emitted as the literal "(none)").
Output (extension-census.csv):
rank,extension,file_count
1,.md,829
...
and extension-census.md (ranked + totals row). Run:
python3 extract_extension_census.py
"""
import csv
import os
import sys
from collections import Counter
REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
SRC = os.path.join(REPO, "repo_files.tsv")
OUT_CSV = os.path.join(REPO, "wizard-work", "ledger", "extension-census.csv")
OUT_MD = os.path.join(REPO, "wizard-work", "ledger", "extension-census.md")
def clean_path(raw: str) -> str:
s = raw.strip()
# De-quote a cell that was wrapped in double quotes (Python repr / json).
if len(s) >= 2 and s[0] == '"' and s[-1] == '"':
s = s[1:-1]
# De-escape backslash escapes: \\ -> \, \" -> ", \n -> newline, \t -> tab.
s = s.encode("latin-1").decode("unicode_escape")
return s
def ext_of(path: str) -> str:
base = os.path.basename(path.rstrip("/"))
if not base or base in (".", ".."):
return "(none)"
if "." in base:
return "." + base.rsplit(".", 1)[1].lower()
return "(none)"
def main() -> int:
counts: Counter = Counter()
total_rows = 0
with open(SRC, newline="", encoding="utf-8") as f:
for line in f:
line = line.rstrip("\n").rstrip("\r")
if not line.strip():
continue
if "\t" not in line:
continue
rank, path = line.split("\t", 1)
path = clean_path(path)
total_rows += 1
ext = ext_of(path)
counts[ext] += 1
# order: by count desc, then extension asc
ordered = sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))
with open(OUT_CSV, "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(["rank", "extension", "file_count"])
for i, (ext, n) in enumerate(ordered, 1):
w.writerow([i, ext, n])
total_files = sum(counts.values())
md = []
md.append("# Extension census")
md.append("")
md.append("Ranked census of file extensions across the troupe worktree "
"(re-derived from `repo_files.tsv` by `extract_extension_census.py`).")
md.append("")
md.append("| rank | extension | file_count |")
md.append("|---|---|---|")
for i, (ext, n) in enumerate(ordered, 1):
md.append("| %d | %s | %d |" % (i, ext, n))
md.append("")
md.append("**Total files: %d**" % total_files)
md.append("**Unique extensions: %d**" % len(ordered))
md.append("")
with open(OUT_MD, "w", encoding="utf-8") as f:
f.write("\n".join(md) + "\n")
print("rows=%d total_files=%d extensions=%d"
% (total_rows, total_files, len(ordered)))
print("top10=%s" % ordered[:10])
return 0
if __name__ == "__main__":
sys.exit(main())