Assignment generator scaffold project
Project description
agen
agen (assignment-generator) is a Python 3.12 CLI tool that reads a source-code template file and generates two output files:
- an assignment file for students (placeholders replace solution blocks)
- a solution file for instructors (full content with solution markers)
Templates are ordinary source files (.py, .c, etc.) annotated with special comment-tagged blocks that control what appears in each output.
Installation
agen requires Python 3.12+ and is managed with uv.
From package index
uv tool install assignment-generator-sebastian-stigler
agen --help
From source
git clone <repository-url>
cd agen
uv sync
This installs the package and all dependencies into a local virtual environment. The agen command is then available via:
uv run agen --help
To install the tool globally (into a dedicated isolated environment):
uv tool install .
agen --help
Configuration
Configuration is resolved by layered merging:
- Built-in defaults (always applied)
- Global config —
~/.config/agen/agen-config.json(overrides defaults) - Local config —
.agen-config.jsonin the current working directory (overrides global)
comment_tokens entries are merged key-by-key; all other keys are replaced wholesale by the later layer.
Generating a starter config
agen generate-config > .agen-config.json
Config file format
{
"comment_tokens": {
".py": "#",
".c": "//"
},
"assignment_marker": "TODO",
"solution_marker_begin": "BEGIN SOLUTION",
"solution_marker_end": "END SOLUTION",
"template_file_prefix": "template_",
"assignment_file_prefix": "assignment_",
"solution_file_prefix": "solution_",
"assignment_only_begin": "BEGIN ASSIGNMENT ONLY",
"assignment_only_end": "END ASSIGNMENT ONLY",
"solution_only_begin": "BEGIN SOLUTION ONLY",
"solution_only_end": "END SOLUTION ONLY",
"assignment_begin": "BEGIN ASSIGNMENT",
"assignment_end": "END ASSIGNMENT"
}
comment_tokens
A mapping of file extensions (including the leading dot) to the line-comment token for that language. agen uses this token when writing marker lines into the output files. Add an entry for every extension you use in templates, for example ".js": "//" or ".sql": "--".
comment_tokens is the only key that is merged key-by-key across config layers — a later layer can add or override individual extensions without replacing the whole map.
Output markers (assignment_marker, solution_marker_begin, solution_marker_end)
These strings control the text that agen writes into the output files:
assignment_marker— the placeholder comment text inserted into the assignment file wherever anASSIGNMENTblock appears.solution_marker_begin/solution_marker_end— comments wrapped around the original block content in the solution file (e.g.# BEGIN SOLUTION…# END SOLUTION).
assignment_marker can be a single line (for example TODO) or multiline text.
assignment_marker supports multiline text. Each non-empty line becomes a commented placeholder line using the configured comment token; empty lines stay empty.
Example config value:
{
"assignment_marker": "YOUR CODE STARTS HERE >>>\n\n<<<< YOUR CODE ENDS HERE"
}
Example assignment output snippet (for a Python template):
def add(a, b):
# YOUR CODE STARTS HERE >>>
# <<<< YOUR CODE ENDS HERE
File prefixes (template_file_prefix, assignment_file_prefix, solution_file_prefix)
These prefixes control automatic output file naming. When agen derives an output path from the template filename it:
- Strips
template_file_prefixfrom the start of the template basename (if present). - Prepends
assignment_file_prefixorsolution_file_prefixto the remainder.
For example, with the defaults a template named template_exercise.py produces assignment_exercise.py and solution_exercise.py. You can override the output path entirely with -a / -s on the command line.
Template block tags (assignment_only_begin/end, solution_only_begin/end, assignment_begin/end)
These are the tag strings that agen looks for inside the template file to delimit the three special block types. Each pair marks where a block starts and ends. They must appear as the sole content of a comment line (after the comment token). Change them only if the defaults conflict with existing comments in your codebase.
Environment variables
| Variable | Default | Description |
|---|---|---|
AGEN_CONFIG_BASENAME |
agen-config.json |
Config file basename (both global and local) |
AGEN_GLOBAL_CONFIG_PATH |
~/.config/agen |
Directory for the global config file |
Template format
Template files are normal source files with specially tagged comment blocks. The file extension determines which line-comment token is used.
Block types
| Block tag | Assignment output | Solution output |
|---|---|---|
ASSIGNMENT_ONLY |
written as-is | omitted |
SOLUTION_ONLY |
omitted | written as-is |
ASSIGNMENT |
replaced by a placeholder comment (TODO) |
wrapped in begin/end solution markers + original content |
| (unmarked) | written as-is | written as-is |
Example template (template_exercise.py)
def add(a, b):
# BEGIN ASSIGNMENT
return a + b
# END ASSIGNMENT
# BEGIN ASSIGNMENT ONLY
# Implement the add() function above.
# END ASSIGNMENT ONLY
# BEGIN SOLUTION ONLY
# Reference implementation — do not distribute.
# END SOLUTION ONLY
Running agen create both template_exercise.py produces:
assignment_exercise.py
def add(a, b):
# TODO
# Implement the add() function above.
solution_exercise.py
def add(a, b):
# BEGIN SOLUTION
return a + b
# END SOLUTION
# Reference implementation — do not distribute.
File naming
By default, agen strips a template_ prefix from the template basename and adds assignment_ or solution_ prefixes to the output files. This is configurable — see Configuration.
Usage
agen [COMMAND] [OPTIONS] [ARGS]
Global options
agen --version
Print the installed agen version.
agen check <templatefile>
Validate and summarise a template file without writing any output.
agen check template_exercise.py
Prints block statistics and any warnings.
agen create assignment <templatefile>
Generate the assignment output file only.
agen create assignment template_exercise.py
agen create assignment template_exercise.py -a custom_assignment.py # custom output path
agen create assignment template_exercise.py -f # overwrite existing file
agen create assignment template_exercise.py --dry-run # preview without writing
agen create assignment template_exercise.py --anyway # skip the no-ASSIGNMENT-block guard
agen create assignment template_exercise.py -v # show template stats
agen create solution <templatefile>
Generate the solution output file only.
agen create solution template_exercise.py
agen create solution template_exercise.py -s custom_solution.py # custom output path
agen create solution template_exercise.py -f # overwrite existing file
agen create solution template_exercise.py --dry-run # preview without writing
agen create solution template_exercise.py -v # show template stats
agen create both <templatefile>
Generate both assignment and solution output files in one command.
agen create both template_exercise.py
agen create both template_exercise.py -f
agen create both template_exercise.py -a out_a.py -s out_s.py
agen create both template_exercise.py --dry-run
agen create both template_exercise.py -v # show template stats
agen current-config
Print the effective merged configuration, colour-coded by origin (default / global / local).
agen current-config
agen generate-config
Print a complete default config JSON document, suitable for redirecting into a config file.
agen generate-config > .agen-config.json
Development
uv sync # install dependencies
uv run pytest # run the test suite
Project details
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 assignment_generator_sebastian_stigler-0.3.1.tar.gz.
File metadata
- Download URL: assignment_generator_sebastian_stigler-0.3.1.tar.gz
- Upload date:
- Size: 44.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"11","id":"bullseye","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8edee6dba35709c9df7de58e2ee82bfa5e078122db43613b62e1699f87a3282c
|
|
| MD5 |
470d26b9f099a29a78c524be563b886c
|
|
| BLAKE2b-256 |
a0ddcbaa33b415e94e24f86404662020b50b1d6badb375d9422001a550e0f11f
|
File details
Details for the file assignment_generator_sebastian_stigler-0.3.1-py3-none-any.whl.
File metadata
- Download URL: assignment_generator_sebastian_stigler-0.3.1-py3-none-any.whl
- Upload date:
- Size: 20.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"11","id":"bullseye","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
013b62e2497adda8a1c06785f3d4aeaa18d669bc8462fe5dd8d1f0a0e2bd590c
|
|
| MD5 |
2c9f895b6fc97cc76549a1ef39351508
|
|
| BLAKE2b-256 |
9c8509bfe08212a715c604e9e5804da77cb05471399444bca180f29adb592d08
|