Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import ast, traceback, sys, io | |
| import subprocess, tempfile, os | |
| # ββ Python static analysis ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def analyze_python(code: str): | |
| errors = [] | |
| warnings = [] | |
| # 1. Syntax check via ast | |
| try: | |
| tree = ast.parse(code) | |
| except SyntaxError as e: | |
| errors.append(f"SyntaxError (line {e.lineno}): {e.msg}") | |
| return errors, warnings, tree if 'tree' in dir() else None | |
| # 2. Walk AST for common issues | |
| for node in ast.walk(tree): | |
| # Bare except | |
| if isinstance(node, ast.ExceptHandler) and node.type is None: | |
| warnings.append(f"Line {node.lineno}: Bare `except:` β catch specific exceptions instead.") | |
| # == None instead of is None | |
| if isinstance(node, ast.Compare): | |
| for op, comp in zip(node.ops, node.comparators): | |
| if isinstance(op, (ast.Eq, ast.NotEq)) and isinstance(comp, ast.Constant) and comp.value is None: | |
| warnings.append(f"Line {node.lineno}: Use `is None` / `is not None` instead of `== None`.") | |
| # Mutable default argument | |
| if isinstance(node, ast.FunctionDef): | |
| for default in node.args.defaults: | |
| if isinstance(default, (ast.List, ast.Dict, ast.Set)): | |
| warnings.append(f"Line {node.lineno}: Mutable default argument in `{node.name}()` β use None instead.") | |
| # Undefined names (basic) | |
| if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load): | |
| pass # would need scope tracking β skipped for simplicity | |
| return errors, warnings, tree | |
| def run_python(code: str): | |
| """Safely run code in a subprocess with timeout.""" | |
| try: | |
| with tempfile.NamedTemporaryFile(suffix=".py", mode="w", delete=False) as f: | |
| f.write(code) | |
| fname = f.name | |
| result = subprocess.run( | |
| [sys.executable, fname], | |
| capture_output=True, text=True, timeout=5 | |
| ) | |
| os.unlink(fname) | |
| stdout = result.stdout.strip() | |
| stderr = result.stderr.strip() | |
| return stdout, stderr | |
| except subprocess.TimeoutExpired: | |
| return "", "β±οΈ Execution timed out (5s limit)." | |
| except Exception as e: | |
| return "", str(e) | |
| def analyze_javascript(code: str): | |
| """Basic JS pattern checks.""" | |
| errors, warnings = [], [] | |
| lines = code.split("\n") | |
| for i, line in enumerate(lines, 1): | |
| s = line.strip() | |
| if s.startswith("var "): | |
| warnings.append(f"Line {i}: Use `let` or `const` instead of `var`.") | |
| if "==" in s and "===" not in s and "!==" not in s: | |
| warnings.append(f"Line {i}: Use `===` instead of `==` for strict equality.") | |
| if "eval(" in s: | |
| errors.append(f"Line {i}: Avoid `eval()` β security risk.") | |
| if s.endswith("{") is False and s and not s.startswith("//") and not s.endswith(";") and not s.endswith("{") and not s.endswith("}") and not s.endswith(","): | |
| pass # too noisy to flag missing semicolons | |
| return errors, warnings | |
| def check_code(code, language): | |
| if not code.strip(): | |
| return "β Please paste some code first." | |
| result_parts = [] | |
| if language == "Python": | |
| errors, warnings, _ = analyze_python(code) | |
| stdout, stderr = run_python(code) | |
| if errors: | |
| result_parts.append("### π΄ Errors\n" + "\n".join(f"- {e}" for e in errors)) | |
| if stderr: | |
| result_parts.append("### π΄ Runtime Error\n```\n" + stderr + "\n```") | |
| if warnings: | |
| result_parts.append("### π‘ Warnings\n" + "\n".join(f"- {w}" for w in warnings)) | |
| if stdout: | |
| result_parts.append("### β Output\n```\n" + stdout + "\n```") | |
| if not errors and not warnings and not stderr: | |
| result_parts.append("### β No issues found!\nCode looks clean.") | |
| elif language == "JavaScript": | |
| errors, warnings = analyze_javascript(code) | |
| if errors: | |
| result_parts.append("### π΄ Errors\n" + "\n".join(f"- {e}" for e in errors)) | |
| if warnings: | |
| result_parts.append("### π‘ Warnings\n" + "\n".join(f"- {w}" for w in warnings)) | |
| if not errors and not warnings: | |
| result_parts.append("### β No issues found!\nCode looks clean.") | |
| else: | |
| result_parts.append("βΉοΈ Basic analysis only for this language.\nPaste your code and check manually for syntax issues.") | |
| return "\n\n".join(result_parts) | |
| def suggest_fix(code, language, analysis_result): | |
| """Rule-based fix suggestions.""" | |
| if not code.strip(): | |
| return "Paste code first." | |
| fixes = [] | |
| if language == "Python": | |
| fixed = code | |
| if "except:" in fixed: | |
| fixed = fixed.replace("except:", "except Exception as e:") | |
| fixes.append("- Replaced bare `except:` with `except Exception as e:`") | |
| if "== None" in fixed: | |
| fixed = fixed.replace("== None", "is None") | |
| fixes.append("- Replaced `== None` with `is None`") | |
| if "!= None" in fixed: | |
| fixed = fixed.replace("!= None", "is not None") | |
| fixes.append("- Replaced `!= None` with `is not None`") | |
| if fixes: | |
| return "### π§ Auto-Fixed Code\n```python\n" + fixed + "\n```\n\n**Changes made:**\n" + "\n".join(fixes) | |
| return "### β No automatic fixes needed.\nReview warnings manually." | |
| elif language == "JavaScript": | |
| fixed = code | |
| if "var " in fixed: | |
| fixed = fixed.replace("var ", "let ") | |
| fixes.append("- Replaced `var` with `let`") | |
| if fixes: | |
| return "### π§ Auto-Fixed Code\n```javascript\n" + fixed + "\n```\n\n**Changes made:**\n" + "\n".join(fixes) | |
| return "### β No automatic fixes needed." | |
| return "Auto-fix not available for this language." | |
| with gr.Blocks(title="Code Error Finder", theme=gr.themes.Soft()) as app: | |
| gr.Markdown("# π Code Error Finder & Fixer\nPaste code β detect errors β get fix suggestions.") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| language = gr.Dropdown( | |
| choices=["Python", "JavaScript", "Other"], | |
| value="Python", | |
| label="Language" | |
| ) | |
| code_input = gr.Code(label="Paste Your Code", language="python", lines=20) | |
| with gr.Column(scale=2): | |
| analysis_out = gr.Markdown(label="Analysis Result") | |
| fix_out = gr.Markdown(label="Fix Suggestions") | |
| with gr.Row(): | |
| check_btn = gr.Button("π Analyze Code", variant="primary") | |
| fix_btn = gr.Button("π§ Suggest Fix", variant="secondary") | |
| check_btn.click(check_code, inputs=[code_input, language], outputs=analysis_out) | |
| fix_btn.click(suggest_fix, inputs=[code_input, language, analysis_out], outputs=fix_out) | |
| gr.Examples( | |
| examples=[ | |
| ["x = None\nif x == None:\n print('is none')\n\ntry:\n y = 1/0\nexcept:\n pass", "Python"], | |
| ["var x = 5;\nif (x == '5') {\n console.log('equal');\n}", "JavaScript"], | |
| ], | |
| inputs=[code_input, language] | |
| ) | |
| app.launch() |