PythonClassroom is a secure, web-based Python IDE and Learning Management System. Practice coding, submit assignments, and get instant feedback in a safe sandboxed environment.
# Welcome to PythonClassroom!
def hello_world():
print("Hello, Future Developer!")
# Run your code safely
hello_world()
Execute code in isolated Docker containers with strict resource limits. No risk to the host system.
Run code and see results immediately. Test against multiple test cases automatically.
Teachers create sections with enrollment links. Students join and start learning instantly.
Targeted remedial tasks and assessments with strict assignment enforcement, plus new teacher controls to regrade all or selected coding submissions using current problem settings.
Teachers can mark tasks and assessments as remedial and assign them to specific students only. Supported in create, edit, and clone flows.
Non-assigned students are blocked from remedial content across student pages and APIs, including problem access, submissions, chats, leaderboards, and assessment attempts.
Teachers can now regrade coding submissions after changing test cases or points — run for all submissions or only checked rows from the submissions table.
Submission review now includes row checkboxes, select-all, and confirmation modals so only targeted submissions are re-evaluated when needed.
Teacher and student analytics now exclude remedial-only records by default so regular class dashboards stay comparable and noise-free.
The release notes modal no longer auto-opens on page load. Users open it manually from the topbar icon when they want to view updates.
Added an idempotent migration script to add remedial targeting columns and indexes for tasks and assessments in deployed environments.
Full pytest suite is green after remedial targeting, submission regrade additions, and route/service regression coverage updates.
Production-ready improvements: Redis-backed Socket.IO message queue for multi-worker support, per-user rate limiting, sandbox concurrency control, Docker logging infrastructure, and optimized WebSocket intervals.
Socket.IO now uses Redis as a message queue, enabling real-time events (chat, notifications, leaderboard) to work correctly across multiple Gunicorn workers. New Redis service added to Docker Compose.
Rate limiting now keys on authenticated user ID instead of IP address. Students behind shared NAT/proxy no longer hit each other's rate limits. Limits are configurable via environment variables.
Docker sandbox uses a semaphore to limit concurrent container executions (default 20, configurable via SANDBOX_MAX_CONCURRENT). Prevents Docker daemon overload under heavy classroom use.
API rate limits increased for classroom workloads. WebSocket background check intervals doubled (30s → 60s). DB connection pool enlarged. Gunicorn default workers increased from 2 to 4.
New styled error page for HTTP 429 responses. Users see a friendly message with a link back to the dashboard instead of a raw error.
Persistent log volume in Docker Compose, automatic log directory creation, and graceful fallback to console-only logging if the log file is not writable.
AI complexity prompts now include line-numbered code for accurate line references. Response parameters (temperature, top_p, max_tokens, seed) are configurable via environment variables. JSON response format enforced.
AI-powered code complexity analysis in the Python Playground — analyzes time and space complexity using LLM providers (OpenRouter, NVIDIA) with multi-provider support and concurrent request handling.
Click 'AI Analysis' in the Playground to analyze your code's time and space complexity using AI. Returns worst-case Big-O notation for both time and space, plus detailed findings with line references.
Choose between OpenRouter and NVIDIA as your AI provider. Configure via the AI_COMPLEXITY_PROVIDER environment variable. Each provider uses optimized request parameters for best results.
AI analysis runs in a bounded thread pool so multiple students can analyze code simultaneously without blocking Flask workers. Configurable pool size via AI_MAX_WORKERS.
Results display with color-coded badges — green for O(1), blue for O(log n), cyan for O(n), yellow for O(n log n), orange for O(n²), red for O(n³), and purple for O(2ⁿ).
The previous AST-based static complexity analyzer has been removed. All complexity analysis now uses AI for more accurate and comprehensive results across all code patterns.
Step-by-step code execution visualizer in the Python Playground — traces code line-by-line with a Python Tutor-style split layout showing stack frames, heap objects, pointer arrows, and cumulative stdout at each step.
Click 'Visualize' in the Playground to trace code execution step-by-step. See exactly what happens at each line — variable assignments, function calls, returns, and exceptions — rendered in a Python Tutor-style layout with Frames and Objects columns.
Navigate through execution steps with First, Prev, Next, Last buttons or drag the step slider to scrub to any point. Step counter badge shows your current position (e.g., 'Step 5 / 42').
Left column shows all stack frames (Global + function calls) with variable names and values. Right column renders heap objects — lists, tuples, sets, dicts, and nested structures — with indexed tables and type headers.
SVG arrows connect variable boxes to their heap objects, showing exactly what each variable points to. Arrows recalculate on every step and on window resize.
CodeMirror gutter arrows and background colors mark the just-executed line (green) and the next line to execute (red/yellow). A legend explains each indicator.
Toggle primitives as heap objects, render list-of-lists as 2D arrays, show exited function frames, nest objects, use text labels instead of arrows, and configure initial jump behavior (first step, error, or last step).
Visualizer and output share a vertical split pane with a draggable gutter. Output can be popped out into a floating, draggable, resizable window for maximum screen real estate.
The visualizer adapts to dark mode — frame highlights, variable boxes, heap tables, pointer arrow colors, column dividers, and split pane gutters all have dedicated dark theme styles.
Five major features: real-time notification system with WebSocket push, student progress dashboard with Chart.js analytics, teacher section analytics with at-risk student detection, CSV bulk student import, and code plagiarism detection with side-by-side diff viewer.
Real-time notifications for announcements, graded submissions, and chat messages. Bell icon in topbar with unread badge, dropdown preview, and full notifications page. Teachers broadcast announcements per section. Pushed via WebSocket with toast alerts.
Personal analytics page with Chart.js charts: submission activity over time, score trends, difficulty performance, question type accuracy. Section breakdown with progress bars, assessment scores, and recent activity feed.
Comprehensive section analytics: score distribution histogram, problem completion rates, common errors, time-to-complete trends, submission activity charts, assessment performance, at-risk student detection (inactivity, low scores, zero solved), and cross-section comparison.
Upload a CSV file to batch-create student accounts and auto-enroll them into a section. Handles new users, existing students, re-activation, and duplicate detection. Downloadable results sheet with temporary passwords. CSV template included.
Pairwise submission similarity analysis using token-based Jaccard (variable-normalized), AST structure comparison, and text similarity. Adjustable threshold slider. Side-by-side diff viewer with matching line highlights, synchronized scrolling, and per-metric breakdowns.
All analytics services use bulk SQL queries with GROUP BY aggregation — zero N+1 patterns. Teacher analytics split into lazy-loaded API endpoints so charts render instantly while student data loads in the background.
Added 165 new tests across 5 test files (notifications: 28, student analytics: 24, teacher analytics: 34, bulk import: 39, plagiarism: 40). Zero regressions.
Complete UI migration to the SB Admin 2 design system with Bootstrap 5 native dark mode, fully offline-capable frontend with locally hosted Nunito font, mobile-first responsive sidebar with overlay and backdrop, teacher messages modal, sticky topbar, and chat dark mode support.
Full migration to SB Admin 2 layout with collapsible sidebar, sticky topbar, gradient branding, and role-based navigation. All 18+ dashboard templates refactored to use the new base layout.
Bootstrap 5 native dark mode with system preference detection, persistent toggle, and full coverage across sidebar, topbar, cards, chat, assessments, lessons, and code editor (Dracula theme auto-sync).
Nunito font now served locally from static/vendor/ — eliminated the last external Google Fonts dependency. CSP headers updated to remove all CDN references. Zero internet required.
Sidebar uses fixed overlay on mobile with close button and tap-outside backdrop. Topbar stays sticky. No more horizontal scroll or overlapping elements on small screens.
New topbar icon with unread badge shows all student messages grouped by problem in a modal. Click to jump directly to the chat thread. Powered by new API endpoint.
Early sidebar state and dark mode are applied before first paint via inline head script. Login splash screen triggers immediately on form submit. Sidebar animation only after first user interaction.
Content-Security-Policy no longer allows cdn.socket.io or cdn.jsdelivr.net — all scripts, styles, and fonts are served from 'self' only.
All existing tests continue to pass with the full UI migration. No regressions introduced.
Fixed path traversal in admin routes, corrected task average score calculation, added Fernet encryption for assessment/problem passwords, modernized SQLAlchemy queries, and enforced password policy on generated temp passwords.
Admin teacher ID image serving now resolves paths from the project root instead of routes/ directory, preventing directory traversal attacks.
Task average score now uses (points earned / points possible) × 100 instead of dividing by problem count. A student earning 58 of 78 points at a 75% threshold correctly passes.
Assessment access passwords and problem access codes now use Fernet encryption instead of plaintext or one-way hashing. Teachers can still view codes after saving.
Password verification now uses hmac.compare_digest() for constant-time comparison, preventing timing side-channel attacks.
Generated temporary passwords now guarantee at least one uppercase, lowercase, and digit character — always passing the password policy check.
Replaced deprecated Query.get() and Query.get_or_404() calls with db.session.get() and db.get_or_404() per SQLAlchemy 2.0 best practices.
Added 30 new regression tests covering path traversal, task scoring, password encryption, Dockerfile paths, and temp password generation.
Extracted shared route guards into helpers, moved AI detection logic into a service layer, and split the 2300-line models.py into a domain-based package — all with zero import breakage.
Created routes/helpers.py with require_enrollment, require_access_code, and require_task_started decorators. Replaces 19 copy-pasted checks and deduplicates ~60 lines of boilerplate route guards.
Moved ~220 lines of heuristic keystroke analysis from the Submission model into a dedicated AIDetectionService class. Model retains thin delegate methods for backward compatibility. 14 pure-Python unit tests added.
Broke the 2300-line models.py into a models/ package: shared.py (db + enums), user.py, course.py, assessment.py, and support.py. All existing imports continue to work unchanged.
All existing tests continue to pass. Added 14 new pure-Python unit tests for the AI detection service with no database dependency and 0.01s execution time.
Reduced leaderboard query count from O(N×M) to O(1), made Gunicorn worker count configurable, optimized background threads, and added missing database indexes.
Leaderboard endpoints now use 2 batch queries instead of N×M individual queries. A class of 100 students × 20 problems runs 2 SQL queries instead of 4,000. Zero frontend changes — identical JSON response.
Worker count is no longer hardcoded. Set GUNICORN_WORKERS in .env to scale for your workload. Default: 2 workers. Also adds auto-recycle (max-requests 1000) to prevent memory leaks.
WebSocket background threads (task activation, deadlines, online status) now use a single app context per thread instead of recreating it every 30 seconds.
Added indexes on Submission.points_earned (leaderboard ordering) and ChatMessage.is_read (unread count queries) for faster lookups.
Enforced iframe sandbox on user-generated content, added per-endpoint rate limiting to sensitive routes, and added baseline security headers to all responses.
All user-generated iframes (lesson content, problem descriptions) are now sandboxed with restricted permissions. Only autoplay and fullscreen are allowed — no camera, microphone, or geolocation. javascript: URIs are blocked.
Login (10/min), register (5/min), code execution (20/min), submissions (10/min), and access code verification (5/min) now have dedicated rate limits to prevent brute-force and sandbox abuse.
Baseline CSP, X-Content-Type-Options, X-Frame-Options, and Referrer-Policy headers added to all responses. Blocks plugin objects, base tag injection, and clickjacking.
Flask-Limiter instance extracted from app.py into its own limiter.py module, enabling route files to import it for decorators without circular import issues.
Fixed path traversal vulnerability, removed dead code, improved performance by eliminating redundant DB queries, and added missing database indexes.
Profile picture and ticket screenshot serving now use safe_join to prevent directory traversal attacks. Replaces os.path.join which allowed reading arbitrary server files.
Removed redundant update_last_seen hook that ran on every page load. Ticket count badge query now only runs for admins on admin pages.
Added indexes on 8 foreign key columns that were causing full table scans. Includes ticket_replies, support_tickets, teacher_applications, assessments, and more.
Removed duplicated anti-cheat functions from app.py that were shadowed by the canonical versions in routes/__init__.py. Added __all__ to prevent future ambiguity.
Demo accounts with weak passwords (teacher123, student123) are now only created in debug mode — no longer in production.
Socket.IO allowed origins are now configurable via SOCKETIO_CORS_ORIGINS env var instead of being hardcoded to accept all origins.
Replaced all HTTP polling with WebSocket (Flask-SocketIO) for instant real-time updates. Chat, tickets, leaderboards, assessments, and online status now update the moment data changes — no more waiting for the next poll cycle.
Chat messages, ticket replies, leaderboard standings, assessment results, online status, and playground access all update instantly via WebSocket events instead of periodic polling.
Messages between teachers and students appear instantly. Ticket replies sync live with status badge updates. No more 5-10 second polling delays.
Teacher results dashboard updates the moment a student starts or submits an attempt. Also refreshes after regrading or deleting attempts.
The grades report table now defaults to sorting by grade, highest to lowest. Students without grades are placed at the bottom.
Three daemon threads monitor task activation, deadline changes, and online status — pushing updates to connected clients the moment they happen.
Eliminated all HTTP polling (5-30 second intervals) across 11 templates. WebSocket replaces polling for chat, tickets, leaderboard, assessments, online status, playground, deadlines, and task activation.
Split the 8,500-line monolithic app.py into modular Flask Blueprints for better maintainability. Routes are organized into auth, admin, teacher, student, and API modules. All existing templates and code continue to work unchanged.
Routes organized into 5 blueprints — auth (15 routes), admin (25 routes), teacher (86 routes), student (17 routes), api (15 routes). Each is a separate file under routes/.
app.py reduced from 8,518 lines to 736 lines. Route code lives in routes/; app.py contains only the app factory, hooks, and blueprint registration.
Docker socket access restricted via TCP proxy. Web container no longer mounts the socket directly, reducing attack surface if the app is compromised.
Batch-loaded questions, eager-loaded students/assessments in key views. Assessment loading and gradebook queries are now 3-10x faster.
Tests for grading service (MCQ/TF/Short Answer/Essay), question versioning, and anti-cheat integrity verification. Run with pytest.
url_for('index'), url_for('view_section'), and all other endpoint names continue to work unchanged in templates and Python code. No migration needed.
Full-featured assessment system with question banks, configurable exams, auto-grading, multi-attempt support, and Excel export — built for classroom quizzes, midterms, and finals.
Create reusable question banks with categories. Supports MCQ (single/multi-select with partial credit), True/False, Short Answer, and Essay question types. Import from GIFT or Aiken format, export to GIFT or CSV.
Create assessments with multiple sections, each with its own title and instructions. Add questions manually or use random blocks to pull from categories. Three delivery modes: All at Once, Page by Page, or One by One.
MCQ, True/False, and Short Answer are graded automatically on submission. Essay questions have a dedicated manual grading interface with per-response feedback.
Configure max attempts (or unlimited) with four grading methods: Highest, Average, First, or Last. Students see an attempt history table to compare all their attempts.
Control exactly what students see at each phase — during attempt, immediately after, while open, and after close. Toggle marks, correctness, right answers, feedback, and more.
Tabbed teacher dashboard with grades report, score distribution chart, item analysis, and manual grading. Export to Excel respecting the configured grading method.
Results pages update instantly via WebSocket when data changes — no polling, no hard reloads. Preserves scroll position, active tab, filters, and charts.
Upload profile pictures with click-to-expand previews, submit and track support tickets with real-time conversation, and change your own password.
Upload a profile picture from your dashboard. Photos appear on leaderboards, submissions, chat, and admin panels. Click any photo to expand it. Default avatar shown when no picture is set.
Submit bug reports, feature requests, or feedback with optional screenshots. Track ticket status, priority, and have threaded conversations with admins.
Ticket replies update instantly via WebSocket — no page refresh needed. Send replies via AJAX with instant display and live status badge sync.
All users can now change their own password from the dashboard dropdown — no need to contact an administrator.
Admins see a dedicated ticket management panel with summary cards, status filters, priority indicators, and inline status updates. Badge count shown in sidebar.
Profile pictures across leaderboards, submissions, chat, and admin pages are clickable — opens a full-size modal preview.
Fixes auto-submit triggering incorrectly when hidden test cases exist, and resolves duplicate code blocks in markdown lesson imports.
Auto-submit now only triggers when all test cases are visible and pass. If hidden test cases exist, students are prompted to click Submit manually instead.
Lesson markdown import now correctly recognizes ```py (short alias) in addition to ```python for interactive code snippets.
Code blocks extracted as interactive snippets are now removed from the rendered HTML, eliminating the duplicate plain-text display.
The lesson markdown parser now normalizes \r\n and \r line endings internally for consistent code block extraction across platforms.
Import full lessons from Markdown via file upload or paste. Headings auto-generate lesson title and pages.
Upload a .md file to auto-create a lesson with multiple pages. # Heading 1 = lesson title, ### Heading 3 = page breaks, code blocks become runnable snippets.
Paste markdown content directly into a textarea to import a lesson — no file needed. Same heading-based parsing as file upload.
The Create Lesson page now features Upload File and Paste Markdown tabs in a collapsible import section.
Text between the # title and the first ### page heading is automatically captured as the lesson description.
Closes all remaining vulnerabilities from the comprehensive security audit (37/37 fixed + 1 mitigated).
Account locks for 15 minutes after 5 consecutive failed login attempts, with automatic reset on successful login.
Problem access codes are now stored as secure hashes instead of plaintext. Includes migration script for existing data.
Admin user creation now enforces the same password policy (min 8 chars, 1 upper, 1 lower, 1 digit).
Typing analytics (512 KB) and session recording (2 MB) payloads are size-capped to prevent DoS attacks.
Major security update with CSRF protection, rate limiting, HTML sanitization, server-side business logic enforcement, and new admin teacher management capabilities.
Global CSRF protection via Flask-WTF. All forms and AJAX requests automatically include CSRF tokens through a base template override.
Flask-Limiter rate limiting on critical endpoints — login (10/min), registration (5/min), code execution (20/min), submissions (10/min), and access code verification (5/min).
Server-side HTML sanitization using Bleach on all user-generated rich content — problem descriptions, lesson pages, and chat messages — preventing stored XSS attacks.
Server-side checks for problem publication status, task scheduling (starts_at), and auto-lock after submission — preventing API-level bypass of access controls.
Admins can now create teacher accounts, promote students to teachers, and demote teachers to students — all with Bootstrap modal confirmations.
Students can no longer register as teachers. Teacher accounts must be created by an administrator.
Critical security fixes that close multiple loopholes students could use to bypass copy/paste blocking, tamper with typing analytics, and evade AI detection.
Typing analytics now include a server-verified integrity token (HMAC). If a student tampers with analytics data via DevTools or a proxy, the submission is automatically flagged as high risk (≥90%).
The IDE now detects when browser developer tools are opened. DevTools open count is reported to the server and factored into the AI confidence score.
File upload is now automatically blocked when copy/paste is disabled for a problem, closing a bypass where students could upload externally-written code.
Drag-and-drop text into the editor is now blocked when copy/paste is disabled, and tracked as a paste event when allowed.
Code injected via editor.setValue() (DevTools console, file upload, file switching) is now tracked as a bulk set event and counted toward the paste ratio in AI detection.
Server-side cross-validation compares client-reported keystrokes against session recording data. Inflated keystroke counts are overridden with server-computed estimates.
Teachers can now watch full replays of student coding sessions to verify work authenticity and understand student problem-solving approaches.
Enable per-problem session recording that captures every keystroke, edit, and code change in the student IDE for full replay.
Watch student coding sessions with a full-featured replay player — play, pause, seek, step through events, and adjust playback speed.
Visual markers on the replay timeline for paste events, focus loss (tab switches), file switches, run, test, and submit actions.
Detects when students switch tabs, leave the app, or close the window — recorded as timeline events with reasons.
Run, test, and submit actions are recorded and displayed as distinct colored markers on the replay timeline.
Hover over the replay timeline slider to see the exact timestamp at any position.
Major update with AI-powered submission analysis, enhanced grading controls, and quality-of-life improvements.
Automatic behavioral analysis detects likely AI-generated submissions using keystroke dynamics, paste patterns, and typing speed.
Configurable late submission handling: disabled, allowed without penalty, or with customizable point deductions per interval.
Schedule tasks with a start date and time — tasks stay hidden from students until they begin.
Require an access code to start a problem. Auto-lock after first submission is also available.
Teachers can see which students are currently online in real-time with live indicators, online vs enrolled stats, and auto-refreshing percentage ring.
Students can create multiple Python files and import between them in both the IDE and Playground.
Add multiple progressive hints per problem with individual point penalties. Track which students used each hint.
Introducing structured lessons with interactive code, markdown import, and clone capabilities.
Create multi-page lessons with rich content and embedded interactive Python code snippets.
Import lesson pages from Markdown files — Python code blocks auto-convert to runnable interactive snippets.
Per-student completion tracking for lesson pages with progress statistics visible to teachers.
Clone entire lessons or tasks (with all pages, problems, test cases, and hints) to other sections.
Import and export problems as Markdown files. Download a blank template for bulk creation.
Preview problems as students see them and test solutions against all test cases including hidden ones.
Improved code editor features, leaderboards, and chat system for a better learning experience.
Students can ask questions about specific problems. Teachers get instant toast notifications for new messages.
Real-time per-task leaderboards with auto-refresh. Student names are anonymized except for the viewer.
Smart code completion for Python keywords, builtins, and local modules in the code editor.
Export section results to Excel (.xlsx) with task and problem selection for flexible grading reports.
Toggle word wrap in any code editor — IDE, lessons, and playground.
Character-level diff highlighting in test results for easier debugging of wrong outputs.