统计项目内调用库、调用函数信息

# -*- coding: utf-8 -*-
# author: cy
# date: 2023/8/3
# aim:
import ast
import pathlib
from collections import defaultdict


def extract_imports_and_calls(file):
    with open(file, "r", encoding="utf8") as file_obj:
        code = file_obj.read()

    imports = set()
    function_calls = defaultdict(int)

    def visit_Import(node):
        for alias in node.names:
            imports.add(alias.name)

    def visit_ImportFrom(node):
        module = node.module
        for alias in node.names:
            imports.add(f"{module}.{alias.name}")

    def get_function_name(node):
        if isinstance(node, ast.Name):
            return node.id
        elif isinstance(node, ast.Attribute):
            object_name = get_function_name(node.value)
            return f"{object_name}.{node.attr}"
        elif isinstance(node, ast.Call):
            return get_function_name(node.func)
        else:
            return None

    def visit_FunctionCall(node):
        function_name = get_function_name(node.func)
        if function_name:
            function_calls[function_name] += 1

    tree = ast.parse(code)
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            visit_Import(node)
        elif isinstance(node, ast.ImportFrom):
            visit_ImportFrom(node)
        elif isinstance(node, ast.Expr) and isinstance(node.value, ast.Call):
            visit_FunctionCall(node.value)

    return imports, function_calls


def generate_report(rpa_dir=None, report_path=None):
    root_obj = pathlib.Path(rpa_dir)
    for project_dir in root_obj.iterdir():
        if not project_dir.is_dir():
            continue

        codes_dir = project_dir / "code" / "codes"
        if not codes_dir.exists():
            continue

        for file in codes_dir.iterdir():
            if not file.is_file() or not file.suffix == ".py":
                continue

            imports, function_calls = extract_imports_and_calls(file)
            print(
                f"File:{file.name} \nimports:{imports}  \nfunction_calls:{function_calls}")
            with open(report_path, "a") as f:
                f.write(f"Project: {project_dir.name}\n")
                f.write(
                    f"File:{file.name} \nimports:{imports}  \nfunction_calls:{function_calls}")
                f.write("\n-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n")
        print("------------  Project ------------ ")


if __name__ == '__main__':
    rpa_dir = r"E:\pbc111\新建文件夹\out\RPA_isearch"  # 改为 C:/rpa_isearch
    report_path = r"C:\Users\Caoyang\Desktop\report.txt"  # 修改路径
    generate_report(rpa_dir=rpa_dir, report_path=report_path)