Created
November 24, 2020 23:32
-
-
Save charmoniumQ/ba58d08917d8a9075b4dcfdc2e42bf0d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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