| """ |
| Code Explainer + Bug Checker (CLI version) |
| -------------------------------------------- |
| Given a code snippet, this pipeline: |
| 1. Explains what the code does (in plain English, via CodeT5) |
| 2. Gives a line-by-line breakdown (via Python's ast module) |
| 3. Checks for real bugs (via pyflakes static analysis) |
| 4. Checks PEP8 style (via pycodestyle) |
| |
| This uses the same underlying modules as streamlit_app.py, so both |
| interfaces give identical, consistent results. |
| |
| Run: |
| pip install -r requirements.txt |
| python app.py |
| """ |
| |
| from transformers import AutoTokenizer, T5ForConditionalGeneration |
| import torch |
| |
| from line_explainer import explain_line_by_line |
| from bug_checker import detect_bugs, check_style |
| |
| DEVICE = "cuda" if torch.cuda.is_available() else "cpu" |
| |
| |
| |
| |
| EXPLAIN_MODEL_NAME = "Salesforce/codet5-base-multi-sum" |
| |
| print("Loading code explainer model...") |
| explain_tokenizer = AutoTokenizer.from_pretrained(EXPLAIN_MODEL_NAME, use_fast=False) |
| explain_model = T5ForConditionalGeneration.from_pretrained(EXPLAIN_MODEL_NAME).to(DEVICE) |
| |
| |
| def explain_code(code: str) -> str: |
| """Returns a one-sentence, plain-English summary of what the code does.""" |
| inputs = explain_tokenizer(code, return_tensors="pt", truncation=True, max_length=512).to(DEVICE) |
| output_ids = explain_model.generate(**inputs, max_length=64, num_beams=5, early_stopping=True) |
| return explain_tokenizer.decode(output_ids[0], skip_special_tokens=True) |
| |
| |
| |
| |
| |
| def analyze_code(code: str): |
| print("\n--- EXPLANATION (summary) ---") |
| explanation = explain_code(code) |
| print(explanation) |
| |
| print("\n--- EXPLANATION (line-by-line) ---") |
| ok, breakdown = explain_line_by_line(code) |
| if ok: |
| print("\n".join(breakdown)) |
| else: |
| print(breakdown) |
| |
| print("\n--- BUG CHECK (static analysis) ---") |
| bug_result = detect_bugs(code) |
| print(bug_result["summary"] if bug_result["syntax_valid"] else bug_result["syntax_error"]) |
| if bug_result["has_bug"] and bug_result["static_issues"]: |
| for issue in bug_result["static_issues"]: |
| print(f" - {issue}") |
| |
| print("\n--- STYLE CHECK (PEP8) ---") |
| if bug_result["syntax_valid"]: |
| style_issues = check_style(code) |
| if style_issues: |
| print(f"{len(style_issues)} style issue(s):") |
| for issue in style_issues: |
| print(f" - {issue}") |
| else: |
| print("No PEP8 style issues found.") |
| else: |
| style_issues = [] |
| print("Skipped (code has a syntax error).") |
| |
| return { |
| "explanation": explanation, |
| "line_by_line": breakdown if ok else None, |
| "bug_result": bug_result, |
| "style_issues": style_issues, |
| } |
| |
| |
| if __name__ == "__main__": |
| sample_code = """def add_numbers(a, b) |
| return a + b""" |
| analyze_code(sample_code) |
|
|
|
|