A simple, elegant Python framework for creating and running interactive quizzes
Project description
Quizy
Overview
A lightweight, API-first Python quiz framework for creating interactive quizzes and assessments. Quizy provides a clean, extensible interface without prescriptive UI constraints, allowing you to build quiz applications that fit your specific needs.
- Async/Await Support: Non-blocking quiz execution with
execute_async() - Live Timer Display: Real-time countdown with visual feedback
- Partial Credit System: Award points for partially correct answers
- Enhanced MatchingQuestion: Answer shuffling and optional partial credit
- Improved CLI: Interactive formatting with progress indicators
- Better Time Management: Per-question and quiz-level time limits with countdown
Important: Unified API
As of v0.3.0, all enhanced features are integrated directly into the core API. There are no separate "improved" modules:
# Single unified import
from quizy import Quiz, MatchingQuestion, QuizCLI, TimerDisplay
# All features are available by default
quiz = Quiz(title="My Quiz", time_limit=60)
1. Async Quiz Execution
Execute quizzes asynchronously for non-blocking operations:
from quizy import Quiz, MultipleChoiceQuestion, QuizCLI
quiz = Quiz(title="Async Quiz")
# ... add questions ...
# Run asynchronously
result = await quiz.execute_async(
answer_provider=async_answer_provider,
question_callback=async_question_callback
)
2. Enhanced MatchingQuestion
New options for better user experience:
from quizy import MatchingQuestion
question = MatchingQuestion(
text="Match items",
pairs={"A": "Apple", "B": "Banana", "C": "Cherry"},
shuffle_answers=True, # NEW: Randomize answer options (default: True)
allow_partial_credit=False, # NEW: Award partial points (default: False)
time_limit=15 # Time limit in seconds
)
Partial Credit Calculation:
- Full match: 100% credit
- Partial match:
correct_matches / total_pairs - Wrong selections: 0% credit
3. Partial Credit for MultipleSelectQuestion
Award partial credit for incomplete correct answers:
from quizy import MultipleSelectQuestion
question = MultipleSelectQuestion(
text="Select all correct answers",
options=["A", "B", "C", "D"],
correct_answers=["A", "B"],
allow_partial_credit=True, # NEW
shuffle_options=True
)
4. Live Timer Display
Display countdown timers with visual feedback:
from quizy import TimerDisplay
# Create a timer for a question
timer = TimerDisplay(duration=15) # 15 seconds
# Check remaining time
remaining = timer.get_remaining()
time_string = timer.format_time(remaining) # "00:05"
# Visual warning
warning = timer.get_warning_symbol() # Returns ⚠️, ⏱️, or ✓
Time Warning Indicators:
✓- Plenty of time (>30s remaining)⏱️- Getting short (10-30s remaining)⚠️- Running out (≤10s remaining)❌- Time expired
5. Enhanced Results with Metrics
New metrics in QuizResult:
result = quiz.execute(answer_provider=provide_answer)
# New properties
print(f"Score: {result.score_percentage:.1f}%") # Includes partial credit
print(f"Partial Answers: {result.partial_answers}") # Count of partial credit
print(f"Avg Time/Question: {result.average_time_per_question:.1f}s")
# New in QuestionResult
for qr in result.question_results:
print(f"Score: {qr.score}") # 0.0 to 1.0 (0.5 for partial)
print(f"Is Partial: {qr.is_partial}")
6. Question Shuffling
Shuffle options for variety and fairness:
from quizy import MultipleChoiceQuestion
# Shuffle for this question
q1 = MultipleChoiceQuestion(
text="What is 2+2?",
options=["3", "4", "5"],
correct_answer="4",
shuffle_options=True
)
# Access shuffled display options
for opt in q1.display_options:
print(opt)
7. Quiz Randomization
Randomize quiz question order:
quiz = Quiz(
title="My Quiz",
randomize_order=True, # Shuffle question order
shuffle_options=True, # Shuffle all question options
show_progress=True # Show progress indicator
)
Enhanced CLI Features
Interactive Formatting
The QuizCLI now provides:
- Color-coded output: Green for correct, red for incorrect, yellow for warnings
- Visual status icons: ✓, ✗, ◐, ⏱, ⊘ for different result types
- Progress indicators: Question numbering with remaining time
- Better prompts: Context-aware input requests
Example Output
============================================================
Question 1/5 | ⏱️ 15s
============================================================
What is the capital of France?
1. London
2. Berlin
3. Paris
4. Madrid
⏱️ Time remaining: 00:12
Your answer (1-4): 3
============================================================
Results: Quiz Title
============================================================
Overall Performance:
Total Questions: 5
Correct Answers: 4
Partial Answers: 1
Score: 90.0%
Time Taken: 00:34
Avg Time/Question: 6.8s
Running Interactive Quiz
from quizy import QuizCLI
# With timer display
QuizCLI.run_interactive(quiz, show_timer=True)
# Async version
await QuizCLI.run_interactive_async(quiz, show_timer=True)
Showing Detailed Results
# Display breakdown for each question
QuizCLI.display_detailed_results(result)
API Compatibility
Unified Single API
v0.3.0 uses a single unified API. All enhanced features are directly integrated:
# Single import source
from quizy import (
Quiz,
MultipleChoiceQuestion,
MatchingQuestion,
QuizCLI,
TimerDisplay
)
# All features available by default
quiz = Quiz(title="My Quiz", time_limit=60)
No "Improved" Modules
There are no separate core_improved.py or cli_improved.py modules. The original core.py and cli.py have been replaced with the enhanced versions.
Performance Considerations
Async vs Sync
Use execute() when:
- Simple synchronous answer providers
- No blocking I/O operations
- Standard quiz application
Use execute_async() when:
- Answer provider makes network calls
- Integrating with web servers (FastAPI, Django)
- Real-time quiz systems
- Complex async workflows
Timer Overhead
Timer display has minimal overhead:
- Time checking: ~0.1ms per check
- Display formatting: ~0.5ms per update
- No separate threads needed (can be added for UI updates)
Migration Guide
From v0.2 to v0.3
-
Questions still work the same:
# v0.2 q = MultipleChoiceQuestion(text="?", options=[...], correct_answer="...") # v0.3 - same, but can add new features q = MultipleChoiceQuestion( text="?", options=[...], correct_answer="...", shuffle_options=True # NEW option )
-
Add timer support gradually:
# Add time_limit to existing questions q.time_limit = 15 # or in constructor
-
Update imports if using enhanced features:
# For async, use core_improved from quizy.core_improved import Quiz
Examples
Complete Example: Timed Quiz with Async
import asyncio
from quizy import (
Quiz,
MultipleChoiceQuestion,
MatchingQuestion,
QuizCLI
)
async def main():
quiz = Quiz(
title="Python Fundamentals",
time_limit=120, # 2 minutes total
allow_skip=False,
shuffle_options=True,
randomize_order=True
)
# Add timed questions
quiz.add_question(MultipleChoiceQuestion(
text="What does OOP stand for?",
options=["Object Oriented Programming", "Other Object Patterns", "Outer Object Procedure"],
correct_answer="Object Oriented Programming",
time_limit=10
))
quiz.add_question(MatchingQuestion(
text="Match methods to descriptions",
pairs={
"__init__": "Constructor",
"__str__": "String representation",
"__len__": "Length"
},
shuffle_answers=True,
allow_partial_credit=False, # Disable by default
time_limit=20
))
# Run async
result = await quiz.execute_async(
answer_provider=async_get_answer,
question_callback=async_display_question
)
QuizCLI.display_result(result)
async def async_get_answer(question, idx):
# Your async answer logic here
return "answer"
async def async_display_question(question, idx, total):
# Your async display logic here
pass
# Run
asyncio.run(main())
Known Limitations
- Terminal-based timer: Countdown display works best in interactive terminals
- Async input: Currently uses blocking
input()- can be enhanced withaioinput - Option shuffling: Once shuffled, cannot be re-shuffled in same instance
- Partial credit: Some question types (Short Text) don't support partial credit
Future Enhancements
Planned for v0.4+:
- Web-based UI components
- Database integration for result persistence
- Advanced analytics and reporting
- Real-time leaderboards
- Ai-powered question generation
- More partial credit options
Support & Contributions
For issues, feature requests, or contributions:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quizy-0.3.2.tar.gz.
File metadata
- Download URL: quizy-0.3.2.tar.gz
- Upload date:
- Size: 20.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4371206140d7c2186478c1dc0fd99d2bb3ac0551f8fb8de9245a061479dc8ce4
|
|
| MD5 |
149baa11f9a26d4bc25345734a8f6404
|
|
| BLAKE2b-256 |
484f7c53b0c16b8196e394cd6a03788dbbb2f28b69f29e9ceb961612283c76d8
|
File details
Details for the file quizy-0.3.2-py3-none-any.whl.
File metadata
- Download URL: quizy-0.3.2-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab1a2010f8e05ddc9f5858724943870e2a51453a5a659fdefef19de4126163c0
|
|
| MD5 |
ffd7b457a7b93a0aad10c07912b49d15
|
|
| BLAKE2b-256 |
085dd28c557e9187f4cda49f235b7ba08a9d499292f1198a57294930879468dc
|