Skip to content

Instantly share code, notes, and snippets.

@charmoniumQ
Created November 24, 2020 23:32
Show Gist options
  • Save charmoniumQ/ba58d08917d8a9075b4dcfdc2e42bf0d to your computer and use it in GitHub Desktop.
Save charmoniumQ/ba58d08917d8a9075b4dcfdc2e42bf0d to your computer and use it in GitHub Desktop.
import textwrap
import subprocess
import json
from pathlib import Path
## Configuration ##
# All langs except real_langs will be ignored
only_include_langs = {"C++", "C", "C Header", "C++ Header", "YAML", "Makefile", "Markdown", "Shell", "CMake", "Python", "Dockerfile"}
exclude_files = set(map(Path, [
"open_vins",
]))
# This is the column to use to weight complexity of the whole project by its components
weight_column = "Lines"
# These are the valid choices
assert weight_column in {"Bytes", "CodeBytes", "Lines", "Code", "Comment", "Blank", "Complexity", "Count", "WeightedComplexity"}
## End of configuration ##
def scc(list_of_paths):
proc = subprocess.run(["scc", "--format=json", *map(str, list_of_paths)], capture_output=True, text=True, check=True)
return json.loads(proc.stdout)
def fd(path, type_=None, max_depth=None):
args = []
if type_ is not None:
args.append(f"--type={type_}")
if max_depth is not None:
args.append(f"--max-depth={max_depth}")
proc = subprocess.run(["fd", *args, ".", str(path)], capture_output=True, text=True, check=True)
return [Path(path) for path in proc.stdout.split("\n") if path != "." and path]
all_langs = set()
breakdown = dict()
def process(component, file_):
breakdown[component] = dict()
if isinstance(file_, list):
files = file_
else:
files = fd(file_, type_="file")
for file_ in files:
breakdown[component][file_] = {}
for block in scc([file_]):
all_langs.add(block["Name"])
if block["Name"] in only_include_langs:
breakdown[component][file_][block["Name"]] = block
root_files = []
for file_ in fd(".", max_depth=1):
if file_ in exclude_files:
pass
elif file_.is_symlink():
pass
elif file_.is_dir():
process(str(file_), file_)
else:
root_files.append(file_)
process(".", root_files)
def shorten(string, width):
if len(string) > width:
cut = int(width * 0.6)
assert width > 3
rest = width - cut - 3
return string[:cut] + "..." + string[-rest:]
else:
return string
print("Excluding langs: " + ", ".join(all_langs - only_include_langs))
print("Individual:")
print(f"{'component':<20s} {'path':<40s} {'language':<10s} {'lines':>6s} {'bytes':>6s} {'complx':>6s}")
for component, files in breakdown.items():
lines = sum(block["Lines"] for blocks in files.values() for block in blocks.values())
complexity = sum(block["Complexity"] for blocks in files.values() for block in blocks.values())
blank = ""
n_files = str(len(files))
# print(f"{component:<20s} {n_files:<4s} {blank:46s} {lines: 5d} {complexity: 4d}")
for file_, blocks in files.items():
file_str = shorten(str(file_), width=40)
for lang, block in blocks.items():
print(f"{component:<20s} {file_str:<40s} {lang:<10s} {block['Lines']: 6d} {block['Bytes']: 6d} {block['Complexity']: 6d}")
print()
print("Aggregated by component:")
print(f"{'component':<20s} {'path':<40s} {'':<10s} {'lines':<6s} {'bytes':>6s} {'complx':>6s}")
for component, files in breakdown.items():
lines = sum(block["Lines"] for blocks in files.values() for block in blocks.values())
complexity = sum(block["Complexity"] for blocks in files.values() for block in blocks.values())
bytes_ = sum(block["Bytes"] for blocks in files.values() for block in blocks.values())
blank = ""
n_files = str(len(files))
print(f"{component:<20s} {n_files:<4s} {blank:46s} {lines: 6d} {bytes_: 6d} {complexity: 6d}")
lines = sum(block["Lines"] for files in breakdown.values() for blocks in files.values() for block in blocks.values())
complexity = sum(block["Complexity"] for files in breakdown.values() for blocks in files.values() for block in blocks.values())
bytes_ = sum(block["Bytes"] for files in breakdown.values() for blocks in files.values() for block in blocks.values())
n_files = str(sum(len(files) for files in breakdown.values()))
component = 'all'
print(f"{component:<20s} {n_files:<4s} {blank:46s} {lines: 6d} {bytes_: 6d} {complexity: 6d}")
print()
print("Aggregated by component (CSV):")
print(f"{'component'},{'path'},{'lines'},{'bytes'},{'complx'}")
for component, files in breakdown.items():
lines = sum(block["Lines"] for blocks in files.values() for block in blocks.values())
complexity = sum(block["Complexity"] for blocks in files.values() for block in blocks.values())
bytes_ = sum(block["Bytes"] for blocks in files.values() for block in blocks.values())
blank = ""
n_files = str(len(files))
print(f"{component},{n_files},{blank},{lines},{bytes_},{complexity}")
lines = sum(block["Lines"] for files in breakdown.values() for blocks in files.values() for block in blocks.values())
complexity = sum(block["Complexity"] for files in breakdown.values() for blocks in files.values() for block in blocks.values())
bytes_ = sum(block["Bytes"] for files in breakdown.values() for blocks in files.values() for block in blocks.values())
n_files = str(sum(len(files) for files in breakdown.values()))
component = 'all'
print(f"{component},{n_files},{blank},{lines},{bytes_},{complexity}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment