Moodle (GIFT) to Paper Exam Generator
Project description
ua-exam
ua-exam is a Python CLI tool designed to automate the creation of physical paper exams from Moodle question banks (GIFT format). It allows instructors to define complex exam structures via a JSON configuration, randomly select questions from hierarchical categories, generate professional LaTeX-ready documents, and support multiple randomized exam copies.
Detailed documentation is available on the GitHub Pages.
Key Features
- Advanced GIFT Parsing:
- Support for
.giftand.txtfiles. - Handles Multiple Choice, True/False, and Open Answer (Essay).
- Support for Multiple Response (partial credits) with multi-answer solution keys.
- Robust handling of questions containing internal blank lines and complex formatting.
- Support for
- Hierarchical Question Bank:
- Recursive scanning of questions folders.
- Automatic indexing by the GIFT
$CATEGORYdirective. - Flexible category matching using a global
category_prefix.
- Smart Randomization & Deduplication:
- Option Shuffling: Choices are randomized for every question to ensure variety.
- Global Deduplication: Prevents the same question from appearing twice in the same exam.
- Reproducibility: Use the seed flag to generate the exact same exam order.
- Multiple Exam Versions (Copies):
- Automatically generate multiple randomized copies of the same exam structure (e.g. Version A, Version B) with sequential seeds.
- Professional LaTeX Layout:
- Native support for LaTeX Math ($...$) and Code Blocks (
code). - Automated university branding (Logo and Header).
- Pre-configured identifying fields (Name, Number, Classification).
- Solutions generated as a CSV file, perfectly mapped to the shuffled choices.
- Native support for LaTeX Math ($...$) and Code Blocks (
- Modular Question Conversion:
- Extensible converter registry to transform GIFT files into other Moodle or LMS formats.
Project Structure
.
├── src/
│ └── ua_exam/
│ ├── __init__.py # Package initialization
│ ├── cli.py # CLI entry point
│ ├── exam_generator.py # Exam generation engine
│ ├── gift_parser.py # GIFT parsing module
│ ├── gift_escaper.py # GIFT escaping/markdown translation module
│ ├── pdf_renderer.py # PDF compilation module
│ ├── converters/ # Modular question format converters
│ └── assets/
│ └── logo_ua_cropped.pdf # Packaged default university logo
├── test/ # Test suite
├── examples/ # Configuration examples
└── assets/
└── logo.svg # Project logo
Installation
Install directly from source or via PyPI using pip or uv:
pip install .
Usage
The ua-exam command-line tool provides three primary subcommands: generate, escape, and convert.
1. Generating Exams (generate)
Generates randomized exam copies from a JSON configuration file.
ua-exam generate -c config.json -s 42 -o out/exam.md --pdf
-c,--config: Path to the JSON configuration file (required).-s,--seed: Base random seed (default: 42).-o,--output: Base output file path (default: exam.md).--pdf: Automatically compile the generated Markdown file into a PDF.
Configuration (config.json)
The config file controls the exam generation logic.
| Field | Description | Default |
|---|---|---|
class |
The name of the course or exam. | "Exam" |
date |
Date string to appear on the header. | Current Date |
lang |
Language for fixed labels (pt or en). |
"pt" |
exam |
Exam type (e.g., "Normal", "Recurso", "Teste 01"). | "Normal" |
logo |
Path to the university logo PDF. | Packaged Logo |
questions_folder |
Root directory of your GIFT/TXT files (used if questions_folders is omitted). |
"." |
questions_folders |
Alternative array of question source folders. Each element can be a string path or an object with path and category_prefix. |
Optional |
category_prefix |
Common prefix for all categories (used globally with questions_folder). |
"" |
target_score |
Total expected score for validation. | 20.0 |
duration |
Exam duration string. | "60 minutos" |
instructions |
General instructions for the exam. | (Generic) |
copies |
Number of randomized copies of the exam to generate. | 1 |
parts |
Array of sections. | Required |
Example Configurations
Example 1: Single Question Folder
{
"class": "Laboratórios de Sistemas e Serviços",
"lang": "pt",
"exam": "Teste 01",
"copies": 3,
"category_prefix": "lss/test01/exam",
"questions_folder": "gift/test01",
"parts": [
{
"part": "Escolha Múltipla",
"classification": 10,
"questions": [
{ "topic": "01-terminal", "quantity": 3 },
{ "topic": "02-virtualizacao", "quantity": 4 }
]
},
{
"part": "Resposta Aberta",
"classification": 10,
"questions": [
{ "topic": "open-questions", "quantity": 4 }
]
}
]
}
Example 2: Multiple Question Folders (with prefixes)
{
"class": "Laboratórios de Sistemas e Serviços",
"lang": "en",
"exam": "Exam",
"copies": 2,
"questions_folders": [
{"path": "gift/test01/en", "category_prefix": "lss/test01/exam"},
{"path": "gift/test02/en", "category_prefix": "lss/test02/exam"}
],
"parts": [
{
"part": "Multiple Choice",
"classification": 10,
"questions": [
{ "topic": "01-terminal", "quantity": 2 },
{ "topic": "02-virtualizacao", "quantity": 2 }
]
}
]
}
2. Escaping and Converting MD to GIFT (escape)
Converts a formatted Markdown file into a Moodle-compatible GIFT file, handling necessary special character escaping.
ua-exam escape -i input.md -o output.gift
3. Modular Question Format Conversion (convert)
Converts GIFT question banks to other question formats (e.g. Moodle XML).
ua-exam convert -i input.gift -f xml -o output.xml
Authors
- Mário Antunes - mariolpantunes
License
This project is licensed under the MIT License - see the LICENSE file for details.
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 ua_exam-0.2.0.tar.gz.
File metadata
- Download URL: ua_exam-0.2.0.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c18f785e4f4c971a8c69199c4dbd7eccce2e435f3c6ba2808b137f8f388db648
|
|
| MD5 |
00aa420f024e4baab6a098bc1adf2a85
|
|
| BLAKE2b-256 |
a40a9ec01797a560228cb5b06822ec96586fa19a6c0921776057731cadff0379
|
File details
Details for the file ua_exam-0.2.0-py3-none-any.whl.
File metadata
- Download URL: ua_exam-0.2.0-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4dcf8377a47044dfa66a0608baaeb00eb2391ce6c0495d906e318740f8d591f3
|
|
| MD5 |
965bcb8fb6ffff165b84349f37e1592d
|
|
| BLAKE2b-256 |
8c7045219a182d1767c27ed1db8d97c1e080f38103943a7b34e4455ff84f4085
|