diff --git a/.gitignore b/.gitignore index 240966a48..6dd3608f1 100644 --- a/.gitignore +++ b/.gitignore @@ -173,3 +173,5 @@ tests/metagpt/utils/file_repo_git htmlcov htmlcov.* *.pkl +*-structure.csv +*-structure.json diff --git a/metagpt/repo_parser.py b/metagpt/repo_parser.py index 9f3a1bac4..5e4d67940 100644 --- a/metagpt/repo_parser.py +++ b/metagpt/repo_parser.py @@ -12,14 +12,12 @@ import json import re import subprocess from pathlib import Path -from pprint import pformat from typing import Dict, List, Optional, Tuple import aiofiles import pandas as pd from pydantic import BaseModel, Field -from metagpt.config import CONFIG from metagpt.logs import logger from metagpt.utils.common import any_to_str from metagpt.utils.exceptions import handle_exception @@ -91,16 +89,16 @@ class RepoParser(BaseModel): def generate_json_structure(self, output_path): """Generate a JSON file documenting the repository structure.""" - files_classes = self.generate_symbols() + files_classes = [i.model_dump() for i in self.generate_symbols()] output_path.write_text(json.dumps(files_classes, indent=4)) def generate_dataframe_structure(self, output_path): """Generate a DataFrame documenting the repository structure and save as CSV.""" - files_classes = self.generate_symbols() + files_classes = [i.model_dump() for i in self.generate_symbols()] df = pd.DataFrame(files_classes) df.to_csv(output_path, index=False) - def generate_structure(self, output_path=None, mode="json"): + def generate_structure(self, output_path=None, mode="json") -> Path: """Generate the structure of the repository as a specified format.""" output_file = self.base_directory / f"{self.base_directory.name}-structure.{mode}" output_path = Path(output_path) if output_path else output_file @@ -109,6 +107,7 @@ class RepoParser(BaseModel): self.generate_json_structure(output_path) elif mode == "csv": self.generate_dataframe_structure(output_path) + return output_path @staticmethod def node_to_str(node) -> (int, int, str, str | Tuple): @@ -322,18 +321,3 @@ class RepoParser(BaseModel): def is_func(node): return isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) - - -def main(): - repo_parser = RepoParser(base_directory=CONFIG.workspace_path / "web_2048") - symbols = repo_parser.generate_symbols() - logger.info(pformat(symbols)) - - -def error(): - """raise Exception and logs it""" - RepoParser._parse_file(Path("test.py")) - - -if __name__ == "__main__": - main() diff --git a/tests/metagpt/test_repo_parser.py b/tests/metagpt/test_repo_parser.py index e69de29bb..e355733f3 100644 --- a/tests/metagpt/test_repo_parser.py +++ b/tests/metagpt/test_repo_parser.py @@ -0,0 +1,25 @@ +from pathlib import Path +from pprint import pformat + +from metagpt.const import METAGPT_ROOT +from metagpt.logs import logger +from metagpt.repo_parser import RepoParser + + +def test_repo_parser(): + repo_parser = RepoParser(base_directory=METAGPT_ROOT / "metagpt" / "strategy") + symbols = repo_parser.generate_symbols() + logger.info(pformat(symbols)) + + assert "tot_schema.py" in str(symbols) + + output_path = repo_parser.generate_structure(mode="json") + assert output_path.exists() + output_path = repo_parser.generate_structure(mode="csv") + assert output_path.exists() + + +def test_error(): + """_parse_file should return empty list when file not existed""" + rsp = RepoParser._parse_file(Path("test_not_existed_file.py")) + assert rsp == []