import streamlit as st
import os
import tempfile
import pandas as pd
from datetime import datetime
from scripts.logger import get_logger
from models.codebert import analyze_with_codebert
from utils.code_utils import pylint_check, extract_code_from_ipynb
from charset_normalizer import detect
logger = get_logger(__name__)
UPLOAD_FOLDER = 'static/uploads'
if not os.path.exists(UPLOAD_FOLDER):
os.makedirs(UPLOAD_FOLDER)
st.markdown("""
Assignment Checker
""", unsafe_allow_html=True)
st.write("Upload your Python (.py) or Jupyter Notebook (.ipynb) file to check its code quality.")
# Input for student ID or name
student_id = st.text_input("Enter Student ID or Name", value="Unknown")
uploaded_files = st.file_uploader("Choose a file", type=['py', 'ipynb'], accept_multiple_files=True)
if uploaded_files is not None:
results = []
for uploaded_file in uploaded_files:
file_path = os.path.join(UPLOAD_FOLDER, uploaded_file.name)
try:
# Save uploaded file
with open(file_path, 'wb') as f:
f.write(uploaded_file.getvalue())
st.write(f"File **{uploaded_file.name}** uploaded successfully!")
is_ipynb = uploaded_file.name.endswith('.ipynb')
with st.spinner("Analyzing code..."):
# Extract code for .ipynb or read .py
if is_ipynb:
code = extract_code_from_ipynb(file_path)
if code is None:
st.error("Error: Could not extract code from .ipynb file.")
results.append({
'Student ID/Name': student_id,
'File Name': uploaded_file.name,
'CodeBERT Feedback': 'Error: Could not extract code from .ipynb file.',
'Pylint Feedback': 'N/A'
})
continue
else:
# Read file and detect encoding
with open(file_path, 'rb') as f:
raw_content = f.read()
detected = detect(raw_content)
encoding = detected['encoding']
logger.debug(f"Detected encoding for {file_path}: {encoding}")
if encoding not in ['utf-8', 'ascii']:
code = raw_content.decode(encoding).encode('utf-8').decode('utf-8')
# Save as UTF-8 for Pylint
temp_file_path = os.path.join(UPLOAD_FOLDER, f"utf8_{uploaded_file.name}")
with open(temp_file_path, 'w', encoding='utf-8') as f:
f.write(code)
file_path = temp_file_path
results.append({
'Student ID/Name': student_id,
'File Name': uploaded_file.name,
'CodeBERT Feedback': 'Error: Could not extract code from .ipynb file.',
'Pylint Feedback': 'N/A'
})
continue
else:
code = raw_content.decode('utf-8')
# For .ipynb files, save extracted code to a temporary .py file
analysis_file_path = file_path
if is_ipynb:
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False, encoding='utf-8') as temp_file:
temp_file.write(code)
analysis_file_path = temp_file.name
logger.debug(f"Temporary file content:\n{code}")
# Analyze with CodeBERT
codebert_feedback = analyze_with_codebert(code)
# Run Pylint
pylint_feedback = pylint_check(analysis_file_path)
# Clean up temporary file if created
if is_ipynb or file_path != os.path.join(UPLOAD_FOLDER, uploaded_file.name):
try:
os.unlink(analysis_file_path)
except Exception as e:
logger.warning(f"Failed to delete temporary file {analysis_file_path}: {e}")
results.append({
'Student ID/Name': student_id,
'File Name': uploaded_file.name,
'CodeBERT Feedback': codebert_feedback,
'Pylint Feedback': pylint_feedback
})
# Display results
st.markdown(f"**Analysis Report**\n\n**CodeBERT Feedback:**\n{codebert_feedback}\n\n**Pylint Feedback:**\n```\n{pylint_feedback}\n```")
except Exception as e:
logger.error(f"Error processing file: {e}")
st.error(f"Error processing file: {str(e)}")
# Save results to Excel
# if results:
# timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# excel_path = os.path.join(UPLOAD_FOLDER, f"analysis_results_{timestamp}.xlsx")
# try:
# df = pd.DataFrame(results)
# df.to_excel(excel_path, index=False)
# st.success(f"Analysis results saved to {excel_path}")
# # Provide download link
# with open(excel_path, 'rb') as f:
# st.download_button(
# label="Download Analysis Results",
# data=f,
# file_name=f"analysis_results_{timestamp}.xlsx",
# mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
# )
# except Exception as e:
# logger.error(f"Error saving results to Excel: {e}")
# st.error(f"Error saving results to Excel: {str(e)}")