#!/usr/bin/env python3
"""
Generate high-quality code review training data locally.
"""
import json
import os
from pathlib import Path
OUTPUT_FILE = Path(__file__).parent.parent / "data" / "processed" / "dev_finetuning_generated.json"
def generate_patterns():
patterns = []
# Python: SQL Injection
patterns.append({
"bad": "def get_user(user_id):\n conn = psycopg2.connect(DB_URL)\n cursor = conn.cursor()\n cursor.execute(f\"SELECT * FROM users WHERE id = {user_id}\")\n return cursor.fetchone()",
"review": "**Issues Found: 3**\n\n1. **SQL Injection:** String formatting in SQL queries allows attackers to inject arbitrary commands.\n2. **Resource Leak:** Connection and cursor are never closed.\n3. **No Error Handling:** Database failures will crash the application.\n\n**Improved Code:**\n```python\nimport psycopg2\nfrom contextlib import contextmanager\n\n@contextmanager\ndef get_db_connection():\n conn = psycopg2.connect(DB_URL)\n try:\n yield conn\n conn.commit()\n except Exception:\n conn.rollback()\n raise\n finally:\n conn.close()\n\ndef get_user(user_id: int) -> dict:\n if not isinstance(user_id, int):\n raise ValueError(\"user_id must be an integer\")\n \n with get_db_connection() as conn:\n with conn.cursor() as cursor:\n cursor.execute(\"SELECT * FROM users WHERE id = %s\", (user_id,))\n return cursor.fetchone()\n```",
"tags": ["python", "sql_injection", "security"]
})
# Python: Mutable Default
patterns.append({
"bad": "def add_item(item, items=[]):\n items.append(item)\n return items",
"review": "**Bug:** Mutable default argument `[]` is shared across all calls. Modifying it in one call affects all subsequent calls.\n\n**Fix:**\n```python\ndef add_item(item, items=None):\n if items is None:\n items = []\n items.append(item)\n return items\n```",
"tags": ["python", "mutable_default", "classic_bug"]
})
# Python: String Concatenation
patterns.append({
"bad": "def build_string(items):\n result = \"\"\n for item in items:\n result += str(item)\n return result",
"review": "**Performance Issue:** String concatenation in a loop is O(n²). Use `str.join()` instead.\n\n**Fix:**\n```python\ndef build_string(items):\n return ''.join(str(item) for item in items)\n```",
"tags": ["python", "performance", "strings"]
})
# JavaScript: Fetch Error Handling
patterns.append({
"bad": "function getUser(id) {\n fetch('/api/users/' + id)\n .then(res => res.json())\n .then(data => console.log(data));\n}",
"review": "**Issues:**\n1. Promise chain is harder to read than async/await.\n2. No error handling for network failures or invalid responses.\n3. String concatenation is error-prone; use template literals.\n\n**Fix:**\n```javascript\nasync function getUser(id) {\n try {\n const response = await fetch(`/api/users/${id}`);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Failed to fetch user:', error);\n }\n}\n```",
"tags": ["javascript", "async", "error_handling"]
})
# JavaScript: Array Mapping
patterns.append({
"bad": "const arr = [1, 2, 3, 4, 5];\nconst doubled = [];\nfor (let i = 0; i < arr.length; i++) {\n doubled.push(arr[i] * 2);\n}",
"review": "**Readability:** Use `Array.map()` for transformations.\n\n**Fix:**\n```javascript\nconst doubled = arr.map(n => n * 2);\n```",
"tags": ["javascript", "readability", "arrays"]
})
# Rust: Borrowing
patterns.append({
"bad": "fn main() {\n let v = vec![1, 2, 3];\n let x = &v[0];\n v.push(4);\n println!(\"{}\", x);\n}",
"review": "**Bug:** Mutable borrow (`v.push()`) while an immutable borrow (`x`) is active. This will fail to compile.\n\n**Fix:**\n```rust\nfn main() {\n let mut v = vec![1, 2, 3];\n let x = v[0]; // Copy, not borrow\n v.push(4);\n println!(\"{}\", x);\n}\n```",
"tags": ["rust", "borrowing", "compile_error"]
})
# Go: Goroutines
patterns.append({
"bad": "package main\nimport \"fmt\"\nfunc main() {\n ch := make(chan int)\n go func() {\n ch <- 42\n }()\n fmt.Println(<-ch)\n}",
"review": "**Issue:** No way to know when the goroutine finishes or if it panicked. Use `sync.WaitGroup` or a done channel.\n\n**Fix:**\n```go\npackage main\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\nfunc main() {\n\tvar wg sync.WaitGroup\n\tch := make(chan int, 1)\n\t\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tch <- 42\n\t}()\n\t\n\tfmt.Println(<-ch)\n\twg.Wait()\n}\n```",
"tags": ["go", "concurrency", "goroutines"]
})
# Security: Env Files
patterns.append({
"bad": "# .env file\nDB_PASSWORD=super_secret_password_123\nAPI_KEY=sk-1234567890abcdef",
"review": "**Security Issue:** Never commit `.env` files to version control. Use `.env.example` with dummy values and add `.env` to `.gitignore`.\n\n**Fix:**\n```bash\n# .gitignore\n.env\n\n# .env.example\nDB_PASSWORD=your_password_here\nAPI_KEY=your_api_key_here\n```",
"tags": ["security", "git", "best_practice"]
})
return patterns
def compile_generated_dataset():
print("=" * 60)
print("Dev-AI Generated Dataset")
print("=" * 60)
all_data = generate_patterns()
# Format for training
training_data = []
for item in all_data:
training_data.append({
"messages": [
{"role": "user", "content": f"Review this code for issues:\n\n```{item['tags'][0]}\n{item['bad']}\n```"},
{"role": "assistant", "content": item['review']}
],
"source": "generated_review",
"tags": item['tags']
})
# Save
os.makedirs(OUTPUT_FILE.parent, exist_ok=True)
with open(OUTPUT_FILE, "w") as f:
json.dump(training_data, f, indent=2)
print(f"Total entries: {len(training_data)}")
print(f"Saved to: {OUTPUT_FILE}")
print("=" * 60)
return training_data
if __name__ == "__main__":
compile_generated_dataset()