diff --git a/harmonizer/ast_semantic_parser.py b/harmonizer/ast_semantic_parser.py index 66885f8..39cf05f 100644 --- a/harmonizer/ast_semantic_parser.py +++ b/harmonizer/ast_semantic_parser.py @@ -117,7 +117,9 @@ def get_intent_concepts( return [word for word in name_words if word in self.known_vocabulary] return list(concepts) - def get_execution_map(self, body: List[ast.AST]) -> Tuple[Dict[ast.AST, str], List[str]]: + def get_execution_map( + self, body: List[ast.AST] + ) -> Tuple[Dict[ast.AST, str], List[str]]: """ Parses the function's body to map each AST node to a semantic dimension and return the list of concepts found. diff --git a/harmonizer/main.py b/harmonizer/main.py index 4fd5b2d..7ecc550 100644 --- a/harmonizer/main.py +++ b/harmonizer/main.py @@ -32,6 +32,7 @@ # --- CONFIGURATION LOADING --- + def load_configuration() -> Dict: """ Searches for and loads .harmonizer.yml from the current directory @@ -65,6 +66,7 @@ def load_configuration() -> Dict: # --- THE HARMONIZER APPLICATION --- + class PythonCodeHarmonizer: """ Analyzes Python code for "Intent Harmony" using the DIVE-V2 @@ -86,7 +88,9 @@ def __init__( ): self.config = config if config else {} self.engine = dive.DivineInvitationSemanticEngine(config=self.config) - self.parser = AST_Semantic_Parser(vocabulary=self.engine.vocabulary.all_keywords) + self.parser = AST_Semantic_Parser( + vocabulary=self.engine.vocabulary.all_keywords + ) self.map_generator = SemanticMapGenerator() self.disharmony_threshold = disharmony_threshold self.quiet = quiet @@ -297,14 +301,20 @@ def parse_cli_arguments() -> argparse.Namespace: formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument("files", nargs="+", help="Python file(s) to analyze") - parser.add_argument("--format", choices=["text", "json"], default="text", help="Output format") - parser.add_argument("--threshold", type=float, default=0.5, help="Disharmony threshold") + parser.add_argument( + "--format", choices=["text", "json"], default="text", help="Output format" + ) + parser.add_argument( + "--threshold", type=float, default=0.5, help="Disharmony threshold" + ) parser.add_argument( "--suggest-refactor", action="store_true", help="Suggest a refactoring for disharmonious functions.", ) - parser.add_argument("--version", action="version", version="Python Code Harmonizer v1.4") + parser.add_argument( + "--version", action="version", version="Python Code Harmonizer v1.4" + ) return parser.parse_args() @@ -350,7 +360,9 @@ def execute_analysis( exit_code = harmonizer.get_highest_severity_code(report) highest_exit_code = max(highest_exit_code, exit_code) if output_format == "text": - formatted = harmonizer.format_report(report, suggest_refactor=suggest_refactor) + formatted = harmonizer.format_report( + report, suggest_refactor=suggest_refactor + ) harmonizer.output_report(formatted) return all_reports, highest_exit_code @@ -377,5 +389,6 @@ def run_cli(): sys.exit(highest_exit_code) + if __name__ == "__main__": run_cli() diff --git a/harmonizer/refactorer.py b/harmonizer/refactorer.py index a6410d0..0bb66a7 100644 --- a/harmonizer/refactorer.py +++ b/harmonizer/refactorer.py @@ -20,7 +20,9 @@ class Refactorer: concrete refactoring strategies. """ - def __init__(self, function_node: ast.FunctionDef, execution_map: Dict[ast.AST, str]): + def __init__( + self, function_node: ast.FunctionDef, execution_map: Dict[ast.AST, str] + ): self.function_node = function_node self.execution_map = execution_map @@ -43,7 +45,10 @@ def suggest_dimensional_split(self) -> str: ast.Expr( value=ast.Call( func=ast.Name(id=new_func_name, ctx=ast.Load()), - args=[ast.Name(id=arg.arg, ctx=ast.Load()) for arg in self.function_node.args.args], + args=[ + ast.Name(id=arg.arg, ctx=ast.Load()) + for arg in self.function_node.args.args + ], keywords=[], ) ) @@ -67,10 +72,7 @@ def suggest_dimensional_split(self) -> str: ast.fix_missing_locations(new_module) final_code = ast.unparse(new_module) - return ( - "# --- Suggested Refactoring: Dimensional Split ---\n\n" - + final_code - ) + return "# --- Suggested Refactoring: Dimensional Split ---\n\n" + final_code def _group_nodes_by_dimension(self) -> Dict[str, List[ast.AST]]: """Groups the function's body nodes by their semantic dimension.""" @@ -79,7 +81,9 @@ def _group_nodes_by_dimension(self) -> Dict[str, List[ast.AST]]: groups[dimension].append(node) return groups - def _create_new_function(self, name: str, body_nodes: List[ast.AST]) -> ast.FunctionDef: + def _create_new_function( + self, name: str, body_nodes: List[ast.AST] + ) -> ast.FunctionDef: """Creates a new function definition from a list of body nodes.""" return ast.FunctionDef( name=name, diff --git a/tests/test_refactorer.py b/tests/test_refactorer.py index 7c09641..0d952a3 100644 --- a/tests/test_refactorer.py +++ b/tests/test_refactorer.py @@ -43,7 +43,11 @@ def test_dimensional_split_refactoring(parser): assert len(suggestion_ast.body) == 4 # 3 new functions + 1 rewritten original # Find the generated functions in the new module - generated_funcs = {node.name: node for node in suggestion_ast.body if isinstance(node, ast.FunctionDef)} + generated_funcs = { + node.name: node + for node in suggestion_ast.body + if isinstance(node, ast.FunctionDef) + } # Check for the presence of all expected functions assert "_validate_and_delete_user_justice" in generated_funcs