feat: Exit on first Python callback exception (closes #133)
By default, McRogueFace now exits with code 1 on the first unhandled exception in timer, click, key, or animation callbacks. This prevents repeated exception output that wastes resources in AI-driven development. Changes: - Add exit_on_exception config flag (default: true) - Add --continue-after-exceptions CLI flag to preserve old behavior - Update exception handlers in Timer, PyCallable, and Animation - Signal game loop via McRFPy_API atomic flags - Return proper exit code from main() Before: Timer exceptions repeated 1000+ times until timeout After: Single traceback, clean exit with code 1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9028bf485e
commit
19ded088b0
12 changed files with 160 additions and 8 deletions
31
tests/notes/test_exception_exit.py
Normal file
31
tests/notes/test_exception_exit.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test for --continue-after-exceptions behavior (Issue #133)
|
||||
|
||||
This test verifies that:
|
||||
1. By default, unhandled exceptions in timer callbacks cause immediate exit with code 1
|
||||
2. With --continue-after-exceptions, exceptions are logged but execution continues
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
import sys
|
||||
|
||||
def timer_that_raises(runtime):
|
||||
"""A timer callback that raises an exception"""
|
||||
raise ValueError("Intentional test exception")
|
||||
|
||||
# Create a test scene
|
||||
mcrfpy.createScene("test")
|
||||
mcrfpy.setScene("test")
|
||||
|
||||
# Schedule the timer - it will fire after 50ms
|
||||
mcrfpy.setTimer("raise_exception", timer_that_raises, 50)
|
||||
|
||||
# This test expects:
|
||||
# - Default behavior: exit with code 1 after first exception
|
||||
# - With --continue-after-exceptions: continue running (would need timeout or explicit exit)
|
||||
#
|
||||
# The test runner should:
|
||||
# 1. Run without --continue-after-exceptions and expect exit code 1
|
||||
# 2. Run with --continue-after-exceptions and expect it to not exit immediately
|
||||
|
||||
print("Test initialized - timer will raise exception in 50ms")
|
||||
38
tests/notes/test_exception_exit_manual.sh
Executable file
38
tests/notes/test_exception_exit_manual.sh
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
# Manual test for --continue-after-exceptions feature (Issue #133)
|
||||
#
|
||||
# This test must be run manually because it verifies exit codes
|
||||
# rather than test output.
|
||||
|
||||
echo "Testing --continue-after-exceptions feature..."
|
||||
echo
|
||||
|
||||
cd "$(dirname "$0")/../../build"
|
||||
|
||||
# Test 1: Default behavior - should exit with code 1 on first exception
|
||||
echo "Test 1: Default behavior (exit on first exception)"
|
||||
timeout 5 ./mcrogueface --headless --exec ../tests/notes/test_exception_exit.py 2>&1
|
||||
EXIT_CODE=$?
|
||||
echo "Exit code: $EXIT_CODE"
|
||||
if [ $EXIT_CODE -eq 1 ]; then
|
||||
echo "[PASS] Exit code is 1 as expected"
|
||||
else
|
||||
echo "[FAIL] Expected exit code 1, got $EXIT_CODE"
|
||||
exit 1
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test 2: --continue-after-exceptions - should keep running until timeout
|
||||
echo "Test 2: --continue-after-exceptions (continue after exception)"
|
||||
timeout 1 ./mcrogueface --headless --continue-after-exceptions --exec ../tests/notes/test_exception_exit.py 2>&1 | tail -5
|
||||
EXIT_CODE=${PIPESTATUS[0]}
|
||||
echo "Exit code: $EXIT_CODE"
|
||||
if [ $EXIT_CODE -eq 124 ]; then
|
||||
echo "[PASS] Timeout killed it (exit code 124) - continued running as expected"
|
||||
else
|
||||
echo "[FAIL] Expected exit code 124 (timeout), got $EXIT_CODE"
|
||||
exit 1
|
||||
fi
|
||||
echo
|
||||
|
||||
echo "All tests PASSED!"
|
||||
Loading…
Add table
Add a link
Reference in a new issue