forked from jjordanbaird/EmailVectorDB
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanalyzer.py
102 lines (82 loc) · 3.91 KB
/
analyzer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import ast
import os
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
class PythonCodeAnalyzer:
def __init__(self, directory=None, output_path=None):
self.directory = directory or os.getcwd()
self.output_path = output_path or "output.txt"
def get_arg_data_type(self, arg):
if arg.annotation:
return ast.unparse(arg.annotation)
else:
return ""
def get_classes_and_methods(self, file_path):
with open(file_path, 'r', encoding='utf-8') as f:
file_contents = f.read()
module = ast.parse(file_contents)
classes_and_methods = {}
for node in module.body:
if isinstance(node, ast.ClassDef):
class_name = node.name
bases = [ast.unparse(base) for base in node.bases]
class_docstring = ast.get_docstring(node)
method_data = {}
for n in node.body:
if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)):
method_name = n.name
args = [(arg.arg, self.get_arg_data_type(arg)) for arg in n.args.args]
return_data_type = ast.unparse(n.returns) if n.returns else "Unknown"
method_docstring = ast.get_docstring(n)
method_data[method_name] = {
"args": args,
"return_data_type": return_data_type,
"docstring": method_docstring
}
classes_and_methods[class_name] = {
"bases": bases,
"docstring": class_docstring,
"methods": method_data
}
return classes_and_methods
def analyze_directory(self):
python_files = []
for root, dirnames, files in os.walk(self.directory):
for file in files:
if file.endswith(".py"):
python_files.append(os.path.join(root, file))
logger.debug(f"Python files found: {python_files}")
result = {}
for file_path in python_files:
try:
classes_and_methods = self.get_classes_and_methods(file_path)
if classes_and_methods:
result[file_path] = classes_and_methods
except Exception as e:
logger.error(f"Error analyzing file {file_path}: {e}")
return result
def save_results(self, results):
with open(self.output_path, 'w', encoding='utf-8') as f:
for file_path, classes_and_methods in results.items():
f.write(f"File: {os.path.relpath(file_path, os.path.dirname(os.getcwd()))}\n")
for class_name, class_data in classes_and_methods.items():
f.write(f" Class: {class_name}\n")
f.write(f" Inherits from: {', '.join(class_data['bases'])}\n")
f.write(f" Docstring: {class_data['docstring']}\n")
for method_name, method_data in class_data['methods'].items():
f.write(f" Method: {method_name}\n")
for arg_name, arg_data_type in method_data['args']:
if arg_data_type:
f.write(f" Arg: {arg_name} ({arg_data_type})\n")
else:
f.write(f" Arg: {arg_name}\n")
f.write(f" Returns: {method_data['return_data_type']}\n")
f.write(f" Docstring: {method_data['docstring']}\n")
def analyze_and_save(self):
results = self.analyze_directory()
logger.debug(f"Analysis results: {results}")
self.save_results(results)
# Usage example
analyzer = PythonCodeAnalyzer(output_path="output.txt")
analyzer.analyze_and_save()