Skip to content

Commit b562104

Browse files
committed
feat(stats): add file sizes and per-language breakdowns to generate_stats.py
1 parent d11ca54 commit b562104

1 file changed

Lines changed: 100 additions & 34 deletions

File tree

backend/generate_stats.py

Lines changed: 100 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,142 @@
11
import sqlite3
22
import os
3-
import re
4-
from collections import Counter
3+
from collections import Counter, defaultdict
54

65
# Paths
76
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
87
DB_PATH = os.path.join(BASE_DIR, "functions.db")
9-
10-
def categorize_type(entity_type, code):
11-
"""Categorize entity into English labels based on native DB types."""
12-
mapping = {
13-
'function': "Functions",
14-
'type': "Types",
15-
'template': "Templates"
16-
}
17-
return mapping.get(entity_type, "Others")
8+
INDEX_PATH = os.path.join(BASE_DIR, "mediawiki.index")
9+
EMBEDDINGS_PATH = os.path.join(BASE_DIR, "embeddings.npy")
10+
11+
EXTENSION_TO_LANGUAGE = {
12+
".py": "Python",
13+
".cpp": "C++",
14+
".hpp": "C++",
15+
".h": "C++",
16+
".cc": "C++",
17+
".cxx": "C++",
18+
".c": "C",
19+
".php": "PHP",
20+
".inc": "PHP",
21+
".js": "JavaScript",
22+
".ts": "TypeScript",
23+
".tsx": "TypeScript",
24+
".mts": "TypeScript",
25+
".cts": "TypeScript",
26+
".lua": "Lua",
27+
".go": "Go",
28+
".java": "Java",
29+
".rs": "Rust",
30+
".rb": "Ruby",
31+
".pl": "Perl",
32+
".pm": "Perl"
33+
}
34+
35+
def get_file_size_string(path):
36+
"""Return human-readable size of file."""
37+
if not os.path.exists(path):
38+
return "Not found"
39+
size_bytes = os.path.getsize(path)
40+
if size_bytes >= 1024**3:
41+
return f"{size_bytes / (1024**3):.2f} GB"
42+
elif size_bytes >= 1024**2:
43+
return f"{size_bytes / (1024**2):.2f} MB"
44+
elif size_bytes >= 1024:
45+
return f"{size_bytes / 1024:.2f} KB"
46+
else:
47+
return f"{size_bytes} bytes"
1848

1949
def get_file_extension(filepath):
2050
"""Extract file extension from path."""
2151
_, ext = os.path.splitext(filepath)
22-
return ext or "no extension"
52+
return ext.lower()
2353

2454
def generate_stats():
55+
# 1. File Size Statistics
56+
print("\n" + "="*50)
57+
print(" MEDIAWIKI SEARCH COMPONENT SIZES")
58+
print("="*50)
59+
print(f"{'Plain Embeddings (embeddings.npy)':<35}: {get_file_size_string(EMBEDDINGS_PATH):>12}")
60+
print(f"{'Metadata Database (functions.db)':<35}: {get_file_size_string(DB_PATH):>12}")
61+
print(f"{'FAISS Search Index (mediawiki.index)':<35}: {get_file_size_string(INDEX_PATH):>12}")
62+
print("="*50)
63+
2564
if not os.path.exists(DB_PATH):
26-
print(f"Error: {DB_PATH} not found.")
65+
print(f"\nError: {DB_PATH} not found. Cannot calculate detailed statistics.")
2766
return
2867

68+
# 2. Database query for counts
2969
conn = sqlite3.connect(DB_PATH)
3070
cursor = conn.cursor()
3171

32-
print("Fetching data from database...")
33-
cursor.execute("SELECT repo_group, filepath, type, code FROM functions")
34-
rows = cursor.fetchall()
72+
print("\nAnalyzing database entries...")
73+
rows = []
74+
try:
75+
cursor.execute("SELECT repo_group, filepath, type FROM functions")
76+
rows = cursor.fetchall()
77+
except Exception as e:
78+
print(f"Error reading database: {e}")
79+
finally:
80+
conn.close()
81+
82+
total_entities = len(rows)
83+
if total_entities == 0:
84+
print("No entries found in database.")
85+
return
3586

3687
repo_group_stats = Counter()
37-
extension_stats = Counter()
88+
lang_stats = Counter()
3889
category_stats = Counter()
90+
lang_type_stats = defaultdict(lambda: Counter()) # language -> {type -> count}
3991

40-
for repo_group, filepath, entity_type, code in rows:
92+
for repo_group, filepath, entity_type in rows:
4193
# Category
42-
category = categorize_type(entity_type, code)
94+
mapping = {'function': 'Functions', 'type': 'Types', 'template': 'Templates'}
95+
category = mapping.get(entity_type, 'Others')
4396
category_stats[category] += 1
4497

4598
# Repo Group
4699
repo_group_stats[repo_group] += 1
47100

48-
# File Extension
101+
# Language mapping
49102
ext = get_file_extension(filepath)
50-
extension_stats[ext] += 1
51-
52-
conn.close()
103+
lang = EXTENSION_TO_LANGUAGE.get(ext, f"Unknown ({ext})" if ext else "No extension")
104+
lang_stats[lang] += 1
105+
lang_type_stats[lang][category] += 1
53106

54107
# Output Results
55-
print("\n" + "="*40)
108+
print("\n" + "="*50)
56109
print(" MEDIAWIKI CODE ENTITY STATISTICS")
57-
print("="*40)
110+
print("="*50)
58111

59112
print("\n--- Statistics by Category ---")
60113
for cat, count in category_stats.most_common():
61-
print(f"{cat:<20}: {count:>8}")
114+
percentage = (count / total_entities) * 100
115+
print(f"{cat:<20}: {count:>8} ({percentage:.1f}%)")
116+
117+
print("\n--- Statistics by Programming Language ---")
118+
# Sort languages by overall frequency
119+
sorted_langs = sorted(lang_stats.items(), key=lambda x: x[1], reverse=True)
120+
for lang, total_count in sorted_langs:
121+
percentage = (total_count / total_entities) * 100
122+
print(f"{lang:<20}: {total_count:>8} ({percentage:.1f}%)")
123+
# Detail types
124+
details = []
125+
for cat in ["Functions", "Types", "Templates", "Others"]:
126+
cnt = lang_type_stats[lang][cat]
127+
if cnt > 0:
128+
details.append(f"{cat}: {cnt}")
129+
if details:
130+
print(f" +- {', '.join(details)}")
62131

63132
print("\n--- Statistics by Repository Group ---")
64133
for group, count in repo_group_stats.most_common():
65-
print(f"{group:<20}: {count:>8}")
66-
67-
print("\n--- Statistics by File Extension ---")
68-
for ext, count in extension_stats.most_common():
69-
print(f"{ext:<20}: {count:>8}")
134+
percentage = (count / total_entities) * 100
135+
print(f"{group:<20}: {count:>8} ({percentage:.1f}%)")
70136

71-
print("\n" + "="*40)
72-
print(f" Total Entities: {len(rows):>18}")
73-
print("="*40)
137+
print("\n" + "="*50)
138+
print(f" Total Code Snippets: {total_entities:>26}")
139+
print("="*50)
74140

75141
if __name__ == "__main__":
76142
generate_stats()

0 commit comments

Comments
 (0)