MISRA_Fixer / app.py
dipesh2025's picture
Update app.py
7fd755a verified
raw
history blame
4.29 kB
import os
import json
import subprocess
from tempfile import NamedTemporaryFile
import gradio as gr
from huggingface_hub import InferenceClient
import wandb
import shutil
import sys
# 1. Initialize W&B (free tier) for basic logging
# non-interactive login
#api_key = os.getenv("WANDB_API_KEY")
#if api_key:
# wandb.login(key=api_key, relogin=True)
# wandb.init(project="dipesh-gen-ai-2025-personal", entity="dipesh-gen-ai-2025")
#else:
# disable wandb entirely if key missing
# wandb.init(mode="disabled")
key = os.getenv("WANDB_API_KEY")
if key:
wandb.login(key=key, relogin=True)
# Always run anonymously (no entity permission needed)
wandb.init(
project="misra-smart-fixer",
mode="online",
anonymous="must"
)
# 2. Hugging Face Inference Client (CPU-only, free quota)
HF_TOKEN = os.getenv("HF_API_TOKEN")
#client = InferenceClient(model="declare-lab/flan-alpaca-gpt4", token=HF_TOKEN)
client = InferenceClient(model="codellama/CodeLlama-7b-hf", token=HF_TOKEN)
def ensure_tool(name: str):
if shutil.which(name) is None:
print(f"Error: `{name}` not found. Please install it and retry.", file=sys.stderr)
sys.exit(1)
def run_cppcheck(source_code: str):
# Check for the code checker tool
ensure_tool("cppcheck")
ext = ".c" if source_code.endswith(".c") else ".cpp"
tf = NamedTemporaryFile(suffix=ext, delete=False)
print("ext" + ext)
tf.write(source_code.encode())
tf.flush()
tf.close()
# Run Cppcheck with MISRA 2012 profile, JSON output
# cmd = [
# "cppcheck", "--enable=all",
# "--std=c++17", "--language=c++",
# "--profile=misra-cpp-2012",
# "--template=json", tf.name
# ]
# select language/std/profile by extension
if tf.name.endswith(".c"):
lang_args = ["--std=c11", "--language=c", "--profile=misra-c-2012"]
print("misra-c-2012")
else:
lang_args = ["--std=c++17", "--language=c++", "--profile=misra-cpp-2012"]
print("misra-cpp-2012")
cmd = ["cppcheck", "--enable=all", *lang_args, "--template=json", tf.name]
res = subprocess.run(cmd, capture_output=True, text=True)
try:
issues = json.loads(res.stderr)
except json.JSONDecodeError:
issues = []
return tf.name, issues
def build_prompt(filename: str, issues: list):
with open(filename) as f:
src = f.read()
if not issues:
return None
summary = "\n".join([
f"- {item['message']} at line {item['line']}"
for item in issues
])
# prompt = f"""
# You are a C++ expert. The code below may violate MISRA C++:2012 rules.
# Source code:
# Issues:
# {summary}
# …"""
# detect language from filename
rule_set = "MISRA C:2012" if filename.endswith(".c") else "MISRA C++:2012"
prompt = f"""
You are a { 'C expert' if filename.endswith('.c') else 'C++ expert' } specializing in {rule_set} compliance.
Here is the source file (`{filename}`):
```
{src}
```
The static analyzer reported the following violations:
{summary}
Produce a unified diff patch that fixes all violations. For each change, include a one‐sentence rationale referencing the violated rule number.
Only return the diff. No extra commentary.
"""
return prompt.strip()
def predict_patch(prompt: str):
response = client.text_generation(prompt, max_new_tokens=256)
patch = response.generated_text
wandb.log({"prompt": prompt, "patch": patch})
return patch
def process_file(file_obj):
#src = file_obj.read().decode()
src = file_obj
print("Source file - ")
print(src)
fname, issues = run_cppcheck(src)
print("Source file issues - ")
print(fname)
print(issues)
prompt = build_prompt(fname, issues)
if prompt is None:
return "No MISRA violations found.", None
patch = predict_patch(prompt)
return "Patch generated below:", patch
# Gradio UI
iface = gr.Interface(
fn=process_file,
inputs=gr.File(file_types=[".c", ".cpp", ".h", ".hpp"]),
outputs=[gr.Text(), gr.Text()],
title="MISRA Smart Fixer",
description="Upload C/C++ code to auto-fix MISRA violations.",
allow_flagging="never"
)
if __name__ == "__main__":
iface.launch(server_name="0.0.0.0", server_port=7860)