QuizGenerator 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quizgenerator-0.3.0/.envrc +3 -0
- quizgenerator-0.3.0/.github/pull_request_template.md +36 -0
- quizgenerator-0.3.0/.github/workflows/release.yaml +149 -0
- quizgenerator-0.3.0/.gitignore +13 -0
- quizgenerator-0.3.0/CLAUDE.md +80 -0
- quizgenerator-0.3.0/CODEOWNERS +1 -0
- quizgenerator-0.3.0/LICENSE +674 -0
- quizgenerator-0.3.0/PKG-INFO +265 -0
- quizgenerator-0.3.0/QuizGenerator/README.md +5 -0
- quizgenerator-0.3.0/QuizGenerator/__init__.py +27 -0
- quizgenerator-0.3.0/QuizGenerator/__main__.py +7 -0
- quizgenerator-0.3.0/QuizGenerator/canvas/__init__.py +13 -0
- quizgenerator-0.3.0/QuizGenerator/canvas/canvas_interface.py +627 -0
- quizgenerator-0.3.0/QuizGenerator/canvas/classes.py +235 -0
- quizgenerator-0.3.0/QuizGenerator/constants.py +149 -0
- quizgenerator-0.3.0/QuizGenerator/contentast.py +1955 -0
- quizgenerator-0.3.0/QuizGenerator/generate.py +253 -0
- quizgenerator-0.3.0/QuizGenerator/logging.yaml +55 -0
- quizgenerator-0.3.0/QuizGenerator/misc.py +579 -0
- quizgenerator-0.3.0/QuizGenerator/mixins.py +548 -0
- quizgenerator-0.3.0/QuizGenerator/performance.py +202 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/__init__.py +0 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/basic.py +103 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst334/__init__.py +1 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst334/languages.py +395 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst334/math_questions.py +297 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst334/memory_questions.py +1400 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst334/ostep13_vsfs.py +572 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst334/persistence_questions.py +396 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst334/process.py +648 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/__init__.py +0 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/gradient_descent/__init__.py +3 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +369 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +305 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +650 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/gradient_descent/misc.py +73 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/math_and_data/__init__.py +2 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +631 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +534 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/models/__init__.py +0 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/models/attention.py +192 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/models/cnns.py +186 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/models/matrices.py +24 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/models/rnns.py +202 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/models/text.py +201 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/models/weight_counting.py +227 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/neural-network-basics/__init__.py +6 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +1308 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/tensorflow-intro/__init__.py +6 -0
- quizgenerator-0.3.0/QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +936 -0
- quizgenerator-0.3.0/QuizGenerator/qrcode_generator.py +293 -0
- quizgenerator-0.3.0/QuizGenerator/question.py +676 -0
- quizgenerator-0.3.0/QuizGenerator/quiz.py +467 -0
- quizgenerator-0.3.0/QuizGenerator/typst_utils.py +113 -0
- quizgenerator-0.3.0/README.md +225 -0
- quizgenerator-0.3.0/documentation/GRADING_GUIDE.md +284 -0
- quizgenerator-0.3.0/documentation/LESSONS_LEARNED-adding_questions.md +707 -0
- quizgenerator-0.3.0/documentation/PARAMETER_STANDARDS.md +111 -0
- quizgenerator-0.3.0/documentation/README.md +158 -0
- quizgenerator-0.3.0/documentation/WEB_UI_INTEGRATION.md +446 -0
- quizgenerator-0.3.0/example_files/all_classes.yaml +184 -0
- quizgenerator-0.3.0/example_files/cst334.yaml +173 -0
- quizgenerator-0.3.0/example_files/cst463.yaml +199 -0
- quizgenerator-0.3.0/example_files/exam_generation.yaml +41 -0
- quizgenerator-0.3.0/example_files/scratch.yaml +72 -0
- quizgenerator-0.3.0/example_files/specific_generators/cst334.caching.yaml +32 -0
- quizgenerator-0.3.0/example_files/specific_generators/cst334.lab-address_translation.yaml +19 -0
- quizgenerator-0.3.0/examples/README.md +55 -0
- quizgenerator-0.3.0/examples/web_ui_integration_example.py +207 -0
- quizgenerator-0.3.0/grade_from_qr.py +472 -0
- quizgenerator-0.3.0/pyproject.toml +75 -0
- quizgenerator-0.3.0/pyproject_prev.toml +75 -0
- quizgenerator-0.3.0/scripts/generate_practice_yaml.sh +17 -0
- quizgenerator-0.3.0/scripts/print.sh +24 -0
- quizgenerator-0.3.0/scripts/vendor_lms_interface.py +335 -0
- quizgenerator-0.3.0/uv.lock +1567 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Pull Request
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
<!-- Provide a brief description of what this PR accomplishes -->
|
|
5
|
+
|
|
6
|
+
## Changes Made
|
|
7
|
+
<!-- List the key changes made in this PR -->
|
|
8
|
+
-
|
|
9
|
+
-
|
|
10
|
+
-
|
|
11
|
+
|
|
12
|
+
## Type of Change
|
|
13
|
+
<!-- Mark the appropriate option with an [x] -->
|
|
14
|
+
- [ ] Bug fix (non-breaking change that fixes an issue)
|
|
15
|
+
- [ ] New feature (non-breaking change that adds functionality)
|
|
16
|
+
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
|
17
|
+
- [ ] Documentation update
|
|
18
|
+
- [ ] Refactoring (no functional changes)
|
|
19
|
+
|
|
20
|
+
## Testing Done
|
|
21
|
+
<!-- Describe the testing you've done to verify your changes -->
|
|
22
|
+
|
|
23
|
+
## Checklist
|
|
24
|
+
<!-- Mark the appropriate options with an [x] -->
|
|
25
|
+
- [ ] My code follows the style guidelines of this project
|
|
26
|
+
- [ ] I have performed a self-review of my own code
|
|
27
|
+
- [ ] I have commented my code, particularly in hard-to-understand areas
|
|
28
|
+
- [ ] I have updated the documentation accordingly
|
|
29
|
+
- [ ] My changes generate no new warnings
|
|
30
|
+
- [ ] Any dependent changes have been merged and published
|
|
31
|
+
|
|
32
|
+
## Screenshots (if applicable)
|
|
33
|
+
<!-- Add screenshots here if they help explain your changes -->
|
|
34
|
+
|
|
35
|
+
## Notes
|
|
36
|
+
<!-- Any additional notes or context about the PR -->
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
name: Release on version bump
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main # change if your default branch is different
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment:
|
|
12
|
+
name: pypi
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write # create tags & releases
|
|
15
|
+
id-token: write # PyPI trusted publishing
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0 # need history to read previous version
|
|
22
|
+
|
|
23
|
+
- name: Set up Python for tooling
|
|
24
|
+
uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: "3.12"
|
|
27
|
+
|
|
28
|
+
- name: Get previous version (from parent commit)
|
|
29
|
+
id: prev_version
|
|
30
|
+
run: |
|
|
31
|
+
BEFORE="${{ github.event.before }}"
|
|
32
|
+
|
|
33
|
+
# First commit / no parent? treat as "no previous version"
|
|
34
|
+
if [ "$BEFORE" = "0000000000000000000000000000000000000000" ] || [ -z "$BEFORE" ]; then
|
|
35
|
+
echo "No previous commit; setting previous version empty."
|
|
36
|
+
echo "version=" >> "$GITHUB_OUTPUT"
|
|
37
|
+
else
|
|
38
|
+
if git show "$BEFORE":pyproject.toml > pyproject_prev.toml 2>/dev/null; then
|
|
39
|
+
VERSION=$(python -c "import tomllib, pathlib; d = tomllib.loads(pathlib.Path('pyproject_prev.toml').read_text()); print(d['project']['version'])")
|
|
40
|
+
echo "previous version: $VERSION"
|
|
41
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
42
|
+
else
|
|
43
|
+
echo "No previous pyproject.toml found; setting previous version empty."
|
|
44
|
+
echo "version=" >> "$GITHUB_OUTPUT"
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
- name: Get current version
|
|
49
|
+
id: curr_version
|
|
50
|
+
run: |
|
|
51
|
+
VERSION=$(python -c "import tomllib, pathlib; d = tomllib.loads(pathlib.Path('pyproject.toml').read_text()); print(d['project']['version'])")
|
|
52
|
+
echo "current version: $VERSION"
|
|
53
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
54
|
+
|
|
55
|
+
- name: Decide whether this is a release commit
|
|
56
|
+
id: decision
|
|
57
|
+
run: |
|
|
58
|
+
PREV="${{ steps.prev_version.outputs.version }}"
|
|
59
|
+
CURR="${{ steps.curr_version.outputs.version }}"
|
|
60
|
+
MSG="${{ github.event.head_commit.message }}"
|
|
61
|
+
|
|
62
|
+
echo "Previous version: '$PREV'"
|
|
63
|
+
echo "Current version: '$CURR'"
|
|
64
|
+
echo "Commit message: '$MSG'"
|
|
65
|
+
|
|
66
|
+
SHOULD_RELEASE=false
|
|
67
|
+
|
|
68
|
+
# Require version change AND 'release' in the commit message
|
|
69
|
+
if [ -n "$CURR" ] && [ "$CURR" != "$PREV" ]; then
|
|
70
|
+
if echo "$MSG" | grep -qi "release"; then
|
|
71
|
+
echo "Version changed and commit message indicates release."
|
|
72
|
+
SHOULD_RELEASE=true
|
|
73
|
+
else
|
|
74
|
+
echo "Version changed but commit message does not contain 'release'; not releasing."
|
|
75
|
+
fi
|
|
76
|
+
else
|
|
77
|
+
echo "Version did not change; not releasing."
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
echo "release=$SHOULD_RELEASE" >> "$GITHUB_OUTPUT"
|
|
81
|
+
|
|
82
|
+
- name: Stop if not a release
|
|
83
|
+
if: steps.decision.outputs.release != 'true'
|
|
84
|
+
run: |
|
|
85
|
+
echo "Not a release commit; skipping remaining steps."
|
|
86
|
+
exit 0
|
|
87
|
+
|
|
88
|
+
- name: Ensure tag does not already exist
|
|
89
|
+
if: steps.decision.outputs.release == 'true'
|
|
90
|
+
run: |
|
|
91
|
+
VERSION="${{ steps.curr_version.outputs.version }}"
|
|
92
|
+
TAG="v${VERSION}"
|
|
93
|
+
|
|
94
|
+
echo "Checking for existing tag $TAG"
|
|
95
|
+
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
|
96
|
+
echo "Tag $TAG already exists. Aborting."
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
- name: Create and push tag
|
|
101
|
+
if: steps.decision.outputs.release == 'true'
|
|
102
|
+
run: |
|
|
103
|
+
VERSION="${{ steps.curr_version.outputs.version }}"
|
|
104
|
+
TAG="v${VERSION}"
|
|
105
|
+
|
|
106
|
+
echo "Creating tag $TAG at $GITHUB_SHA"
|
|
107
|
+
|
|
108
|
+
git config user.name "github-actions[bot]"
|
|
109
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
110
|
+
|
|
111
|
+
git tag "$TAG" "$GITHUB_SHA"
|
|
112
|
+
git push origin "$TAG"
|
|
113
|
+
|
|
114
|
+
- name: Install uv
|
|
115
|
+
if: steps.decision.outputs.release == 'true'
|
|
116
|
+
uses: astral-sh/setup-uv@v6
|
|
117
|
+
|
|
118
|
+
- name: Install Python 3.13 for build
|
|
119
|
+
if: steps.decision.outputs.release == 'true'
|
|
120
|
+
run: uv python install 3.13
|
|
121
|
+
|
|
122
|
+
- name: Build
|
|
123
|
+
if: steps.decision.outputs.release == 'true'
|
|
124
|
+
run: uv build
|
|
125
|
+
|
|
126
|
+
- name: Upload dist artifacts
|
|
127
|
+
if: steps.decision.outputs.release == 'true'
|
|
128
|
+
uses: actions/upload-artifact@v4
|
|
129
|
+
with:
|
|
130
|
+
name: dist
|
|
131
|
+
path: dist/
|
|
132
|
+
|
|
133
|
+
- name: Publish to PyPI
|
|
134
|
+
if: steps.decision.outputs.release == 'true'
|
|
135
|
+
run: uv publish
|
|
136
|
+
|
|
137
|
+
- name: Create GitHub Release
|
|
138
|
+
if: steps.decision.outputs.release == 'true'
|
|
139
|
+
uses: softprops/action-gh-release@v2
|
|
140
|
+
with:
|
|
141
|
+
tag_name: v${{ steps.curr_version.outputs.version }}
|
|
142
|
+
name: v${{ steps.curr_version.outputs.version }}
|
|
143
|
+
body: |
|
|
144
|
+
Release v${{ steps.curr_version.outputs.version }}
|
|
145
|
+
|
|
146
|
+
- Version bumped in pyproject.toml
|
|
147
|
+
- Built with uv and published to PyPI.
|
|
148
|
+
- Artifacts attached below.
|
|
149
|
+
files: dist/*
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
This is a Python-based teaching tools project focused on quiz generation and Canvas LMS integration. The main entry point is `generate_quiz.py`, which generates quizzes in both PDF format and Canvas variations based on YAML configuration files.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
### Core Modules
|
|
12
|
+
- **QuizGenerator/**: Main quiz generation engine
|
|
13
|
+
- `quiz.py`: Core Quiz class that loads from YAML and generates output
|
|
14
|
+
- `question.py`: Question classes and registry system for different question types
|
|
15
|
+
- `premade_questions/`: Collection of specialized question generators (memory, processes, persistence, etc.)
|
|
16
|
+
- `misc.py`: Utilities for output formats and content handling
|
|
17
|
+
|
|
18
|
+
- **lms_interface/**: Canvas LMS integration (submodule)
|
|
19
|
+
- `canvas_interface.py`: CanvasInterface and CanvasCourse classes for API interaction
|
|
20
|
+
- `classes.py`: Data models for LMS objects
|
|
21
|
+
|
|
22
|
+
### Question System
|
|
23
|
+
The project uses a plugin-based question system where question types are defined as classes in `premade_questions/` and registered dynamically. Questions are defined in YAML files that specify the class name and parameters.
|
|
24
|
+
|
|
25
|
+
### Configuration Files
|
|
26
|
+
Quiz configurations are stored in `example_files/` as YAML files. The default configuration is `exam_generation.yaml`, which defines question types, point values, and organization.
|
|
27
|
+
|
|
28
|
+
## Development Commands
|
|
29
|
+
|
|
30
|
+
### Environment Setup
|
|
31
|
+
```bash
|
|
32
|
+
# The project uses uv for dependency management
|
|
33
|
+
uv sync
|
|
34
|
+
source .venv/bin/activate
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Running the Main Script
|
|
38
|
+
```bash
|
|
39
|
+
# Generate PDFs only
|
|
40
|
+
python generate_quiz.py --num_pdfs 3
|
|
41
|
+
|
|
42
|
+
# Generate Canvas quizzes (requires course_id)
|
|
43
|
+
python generate_quiz.py --num_canvas 5 --course_id 12345
|
|
44
|
+
|
|
45
|
+
# Use production Canvas instance
|
|
46
|
+
python generate_quiz.py --prod --num_canvas 2 --course_id 12345
|
|
47
|
+
|
|
48
|
+
# Custom quiz configuration
|
|
49
|
+
python generate_quiz.py --quiz_yaml example_files/custom_quiz.yaml --num_pdfs 2
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Quality Tools
|
|
53
|
+
The project includes development dependencies for code quality:
|
|
54
|
+
```bash
|
|
55
|
+
# Code formatting
|
|
56
|
+
black .
|
|
57
|
+
|
|
58
|
+
# Linting
|
|
59
|
+
flake8
|
|
60
|
+
|
|
61
|
+
# Type checking
|
|
62
|
+
mypy QuizGenerator/
|
|
63
|
+
|
|
64
|
+
# Testing
|
|
65
|
+
pytest
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### LaTeX Dependencies
|
|
69
|
+
PDF generation requires LaTeX with `latexmk`. Generated PDFs are output to the `out/` directory.
|
|
70
|
+
|
|
71
|
+
## Key Files and Patterns
|
|
72
|
+
|
|
73
|
+
- Quiz configurations follow the pattern in `example_files/exam_generation.yaml`
|
|
74
|
+
- New question types should extend base classes in `question.py` and be placed in `premade_questions/`
|
|
75
|
+
- The project uses logging extensively - check `teachingtools.log` for detailed output
|
|
76
|
+
- Canvas integration requires environment variables for API keys (see `.env` symlink)
|
|
77
|
+
|
|
78
|
+
## Testing Notes
|
|
79
|
+
|
|
80
|
+
The project includes a test mode accessible via `python generate_quiz.py TEST`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @samogden
|