Spaces:
Sleeping
Sleeping
File size: 6,617 Bytes
b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c 2d2c6e4 b92d20c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | """
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
FILE: dataset_loader.py
FOLDER: server/
PURPOSE: Loads PR diffs from HuggingFace dataset β feeds the environment
USED BY: server/environment.py, server/app.py
KEY CLASSES/FUNCTIONS: DatasetLoader
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
"""
import random
import logging
from typing import Dict, Any
try:
from datasets import load_dataset
DATASETS_AVAILABLE = True
except ImportError:
DATASETS_AVAILABLE = False
logger = logging.getLogger(__name__)
FALLBACK_SAMPLES = [
{
"filename": "utils/pagination.py",
"patch": "def get_page_items(items, page, page_size):\n- start = page * page_size\n- end = start + page_size\n- return items[start:end]\n+ start = (page - 1) * page_size\n+ end = start + page_size\n+ return items[start:end]",
"comment": "Line 2: page indexing was wrong β pages are 1-indexed so (page-1)*page_size is correct",
},
{
"filename": "api/userController.js",
"patch": "- const userName = user.profile.name;\n+ const userName = user?.profile?.name ?? 'Anonymous';",
"comment": "Missing null check β user.profile could be undefined causing TypeError",
},
{
"filename": "db/queries.py",
"patch": '- query = f"SELECT * FROM users WHERE id = {user_id}"\n+ query = "SELECT * FROM users WHERE id = %s"\n+ cursor.execute(query, (user_id,))',
"comment": "Critical: SQL injection vulnerability β never format user input into queries",
},
{
"filename": "services/emailService.js",
"patch": "- const result = sendEmail(user.email, template);\n+ const result = await sendEmail(user.email, template);",
"comment": "Missing await β sendEmail is async, without await result is a Promise not the value",
},
{
"filename": "core/processor.py",
"patch": '- except:\n+ except (ValueError, TypeError) as e:\n+ logger.error(f"Processing failed: {e}")',
"comment": "Bare except catches everything including SystemExit β always catch specific exceptions",
},
]
class DatasetLoader:
"""
Loads real PR diffs from the microsoft/CodeReviewer dataset.
Falls back to 5 synthetic samples if HuggingFace is unavailable.
"""
def __init__(self):
"""Initializes the dataset loader, attempting to pull from HF."""
self.dataset = None
self.is_loaded = False
# We try to load dataset if HF `datasets` library is available
if DATASETS_AVAILABLE:
try:
# Use a specific split or subset if possible, but CodeReviewer is large.
# We'll just configure it gracefully.
logger.info("Attempting to load 'microsoft/CodeReviewer' dataset...")
# To avoid downloading 20GB in hackathon setup, we might load with streaming=True
# But typically we can just rely on the fallback samples if it takes too long.
ds = load_dataset(
"microsoft/CodeReviewer", split="train", streaming=True
)
# Keep a robust iterator bounded cache
self._iterator = iter(ds)
self.is_loaded = True
except Exception as e:
logger.warning(
f"Failed to load HuggingFace dataset: {e}. Using fallback samples."
)
else:
logger.warning("datasets module not found. Using fallback samples.")
self.samples = []
for sample in FALLBACK_SAMPLES:
sample["language"] = self.get_language_from_filename(sample["filename"])
self.samples.append(sample)
def get_random_sample(self) -> Dict[str, Any]:
"""Returns a random PR diff sample."""
if self.is_loaded and self._iterator:
try:
# Try getting next valid sample from HF stream
for _ in range(50): # try up to 50 times to find bounded patch
record = next(self._iterator)
patch = record.get("patch", "")
if 50 <= len(patch) <= 2000:
return {
"filename": record.get("filename", "unknown"),
"patch": patch,
"comment": record.get("comment", ""),
"language": self.get_language_from_filename(
record.get("filename", "unknown")
),
"msg": record.get("msg", ""),
}
except Exception as e:
logger.warning(
f"Error fetching from dataset stream: {e}. Falling back to default."
)
self.is_loaded = False # fallback forever
# Return fallback if streaming failed or isn't loaded
return random.choice(self.samples)
def get_language_from_filename(self, filename: str) -> str:
"""Detects programming language from file extension."""
ext = filename.split(".")[-1].lower() if "." in filename else ""
mapping = {
"py": "python",
"js": "javascript",
"ts": "typescript",
"java": "java",
"cpp": "cpp",
"c": "c",
"go": "go",
"rs": "rust",
"rb": "ruby",
"cs": "csharp",
"php": "php",
"html": "html",
"css": "css",
"json": "json",
}
return mapping.get(ext, "unknown")
def get_dataset_stats(self) -> Dict[str, Any]:
"""Returns dummy stats or real stats for the `/stats` endpoint."""
lang_counts = {}
for s in self.samples:
lang_counts[s["language"]] = lang_counts.get(s["language"], 0) + 1
return {
"total_samples": (
len(self.samples) if not self.is_loaded else "1M+ (Streaming)"
),
"languages_breakdown": lang_counts if not self.is_loaded else "Mixed",
"avg_patch_length": sum(len(s.get("patch", "")) for s in self.samples)
/ max(1, len(self.samples)),
"source": (
"microsoft/CodeReviewer" if self.is_loaded else "Fallback Synthetic"
),
}
|