1+ import csv
12from pathlib import Path
23
34root_repository = Path (__file__ ).resolve ().parents [2 ]
78algorithms = {}
89total_files = 0
910total_loc = 0
11+ total_comments = 0
1012
1113# Recursively find all files ending with .py
1214for file_path in root_repository .rglob ("*.py" ):
2224 # Extract file name including its relative path to project, this accounts for files under sub-folder in their categories
2325 file_name = Path (* relative_path .parts [1 :])
2426
25- # Count of LOC for each file
27+ # Count of LOC and Comments for each file
2628 loc = 0
27- with open (file_path , "r" , encoding = "utf-8" ) as f :
28- for line in f :
29+ comments = 0
30+
31+ with open (file_path , "r" , encoding = "utf-8" ) as file :
32+ for line in file :
2933 if line .strip ():
3034 loc += 1
35+
36+ if line .strip ().startswith ("#" ):
37+ comments += 1
3138
3239 # Exclude empty Python package initialization files to reduce noise
3340 if file_path .name == "__init__.py" and loc == 0 :
3441 continue
3542
3643 total_files += 1
3744 total_loc += loc
45+ total_comments += comments
3846
3947 if category not in algorithms :
4048 algorithms [category ] = {}
4149
42- algorithms [category ][str (file_name )] = loc
50+ algorithms [category ][str (file_name )] = {
51+ "loc" : loc ,
52+ "comments" : comments ,
53+ "comment_density" : comments / loc if loc > 0 else 0
54+ }
4355
44- print ("Category:" , category )
45- print ("File:" , file_name )
46- print ("LOC:" , algorithms [category ][str (file_name )])
47- print ()
56+ # Can enable in the future with command and switch
57+ # print("Category:", category)
58+ # print("File:", file_name)
59+ # print("LOC:", algorithms[category][str(file_name)])
60+ # print("Comments:", comments)
61+ # print("Comments Density:", algorithms[category][str(file_name)]["comment_density"])
62+ # print()
4863
4964# Output formatting
5065col1 = 28
5166col2 = 8
5267col3 = 12
53- dashes = col1 + col2 + col3 + 2
68+ dashes = col1 + col2 + col3 + col3 + col3 + 3
5469
5570print ("-" * dashes )
56- print (f"{ 'Category' :<{col1 }} { 'Files' :>{col2 }} { 'LOC' :>{col3 }} " )
71+ print (f"{ 'Category' :<{col1 }} { 'Files' :>{col2 }} { 'LOC' :>{col3 }} { 'Comments' :>{col3 }} { '> Density %' :>{col3 }} " )
72+ print ("-" * dashes )
5773
5874for category , files in algorithms .items ():
5975 file_count = len (files )
60- category_loc = sum (files .values ())
6176
62- print (f"{ category :<{col1 }} { file_count :>{col2 }} { category_loc :>{col3 }} " )
77+ # Get the values of loc for each file
78+ category_loc = sum (metrics ['loc' ] for metrics in files .values ())
79+ category_comments = sum (metrics ['comments' ] for metrics in files .values ())
80+ category_comment_density = category_comments / category_loc if category_loc > 0 else 0
81+
82+ print (f"{ category :<{col1 }} { file_count :>{col2 }} { category_loc :>{col3 }} { category_comments :>{col3 }} { category_comment_density * 100 :>{col3 }.2f} " )
6383
6484print ("-" * dashes )
65- print (f"{ len (algorithms ):<{col1 }} { total_files :>{col2 }} { total_loc :>{col3 }} " )
85+
86+ # Calculate Total Comments Density
87+ total_comment_density = total_comments / total_loc if total_loc > 0 else 0
88+
89+ print (f"{ f'Total ({ len (algorithms )} categories)' :<{col1 }} { total_files :>{col2 }} { total_loc :>{col3 }} { total_comments :>{col3 }} { total_comment_density * 100 :>{col3 }.2f} \n " )
90+
91+ # Write results to a csv file
92+ output_file = Path (__file__ ).resolve ().parent / "loc_results.csv"
93+
94+ print ("Saving results to file..." )
95+ with open (output_file , "w" , encoding = "utf-8" , newline = "" ) as csv_file :
96+ writer = csv .writer (csv_file )
97+
98+ # Insert the header
99+ writer .writerow (["Category" , "File" , "LOC" , "Comments" , "Comments Density %" ])
100+
101+ # Insert data rows
102+ for category , files , in algorithms .items ():
103+ for file_name , metrics in files .items ():
104+ writer .writerow ([category , file_name , metrics ["loc" ], metrics ["comments" ], metrics ["comment_density" ] * 100 ])
105+
106+ print ()
107+ print (f"Results saved to: { output_file .name } " )
0 commit comments