exam module

Functions

exam.make_answer_key(exam)

Creates an answer key for a multiple-choice exam by wrapping each correct answer option in a \hl{} command for highlighting.

Parameters:

exam (MCExam) – An MCExam instance whose elements will be copied and annotated.

Returns:

A deep copy of exam.elements with correct options highlighted.

Return type:

dict

Classes

class exam.MCQuestion(question_string=None, correct_string=None)

Stores and manages the content of a single multiple-choice question.

The \all and \none special tokens are recognised only when they appear on a \item line, so occurrences of those strings elsewhere in the question body are not misread as answer choices. Detected tokens are removed from the options list and tracked as boolean flags so they are always appended last during export.

Parameters:
  • question_string (str, optional) – The full LaTeX content of the question, including its options block. Defaults to None.

  • correct_string (str, optional) – The marker that identifies the correct answer (e.g., 'CORRECT'). Defaults to None.

correct_string: str

The marker token used to identify correct answer options.

question_string: str

The original full LaTeX string for the question.

question_header: str

The \shuffle{...} or \noshuffle{...} header portion of the question.

to_shuffle: bool

Whether the options should be shuffled. False when \noshuffle is used.

options: list of str

List of answer option strings (each prefixed with \item). The \all and \none options are not stored here; they are tracked as boolean flags and appended during export.

all_of_above: bool

Whether an “All of the above” option is present.

none_of_above: bool

Whether a “None of the above” option is present.

all_of_above_correct: bool

Whether “All of the above” is the correct answer.

none_of_above_correct: bool

Whether “None of the above” is the correct answer.

shuffle_options(rng)

Returns a new MCQuestion with answer options in a randomized order. The \all and \none options are unaffected because they are stored as flags and always appended last during export.

Parameters:

rng (numpy.random.Generator) – Random number generator used for shuffling.

Returns:

A new MCQuestion instance with options reordered.

Return type:

MCQuestion

add_periods(include_equations=True, correct_string=None)

Adds a period to the end of each option’s main text if one is absent. When an option ends with a LaTeX math expression ($...$), a period is appended only when include_equations is True. The correct-answer token is moved to the very end of the comment.

Parameters:
  • include_equations (bool, optional) – Whether to add a period after trailing math expressions. Defaults to True.

  • correct_string (str, optional) – Override for the correct-answer token. Defaults to None, which falls back to self.correct_string.

Returns:

None

capitalize_first(correct_string=None)

Capitalizes the first letter of each option’s main text.

Parameters:

correct_string (str, optional) – Override for the correct-answer token (accepted for a consistent signature but unused here). Defaults to None.

Returns:

None

class exam.MCGroup(group_lines, correct_string)

Stores and manages a group of related multiple-choice questions delimited by \begin{mcgroup}{N}{header} and \end{mcgroup} in the LaTeX source.

Parameters:
  • group_lines (list of str) – Lines of LaTeX that make up the group block, excluding the \end{mcgroup} line.

  • correct_string (str) – The marker for correct answers, passed through to each MCQuestion.

correct_string: str

The marker token used to identify correct answer options.

group_header: str

The descriptive header text from the \begin{mcgroup}{N}{header} line.

group_count: int

The number of questions in the group (taken from the parsed source and corrected to match the actual count if they differ).

elements: dict

Mapping of integer index to MCQuestion objects within this group.

shuffle_questions(rng)

Returns a new MCGroup with questions in a randomized order.

Parameters:

rng (numpy.random.Generator) – Random number generator used for shuffling.

Returns:

A deep copy of this group with questions reordered.

Return type:

MCGroup

shuffle_options(rng)

Returns a new MCGroup with each question’s options shuffled.

Parameters:

rng (numpy.random.Generator) – Random number generator used for shuffling.

Returns:

A deep copy of this group with options reordered.

Return type:

MCGroup

add_periods(include_equations=True, correct_string=None)

Adds periods to option text for all questions in the group. See MCQuestion.add_periods for full parameter details.

Parameters:
  • include_equations (bool, optional) – Whether to add a period after trailing math expressions. Defaults to True.

  • correct_string (str, optional) – Override for the correct-answer token. Defaults to None.

Returns:

None

capitalize_first(correct_string=None)

Capitalizes the first letter of each option for all questions in the group.

Parameters:

correct_string (str, optional) – Override for the correct-answer token. Defaults to None.

Returns:

None

class exam.MCExam(exam_file=None, exam_lines=None, correct_string='CORRECT', seed=None)

Stores and manages the content of a multiple-choice exam. Reads a LaTeX file, isolates the mcquestions environment, and parses it into MCQuestion and MCGroup objects. Also builds the answer key and computes letter labels.

When exam_file is None the instance is initialized to a valid empty state. The preferred way to build an MCExam from a string rather than a file is MCExam.from_string().

Parameters:
  • exam_file (str, optional) – Path to the LaTeX exam file. Defaults to None.

  • exam_lines (list of str, optional) – Pre-read lines (currently unused; kept for API compatibility). Defaults to None.

  • correct_string (str, optional) – Marker for the correct answer. Defaults to 'CORRECT'.

  • seed (int, optional) – Seed for the internal random number generator. Defaults to None.

correct_string: str

The marker token used to identify correct answer options.

filepath: pathlib.Path

Resolved absolute path to the source file, or None if no file was given.

filename: str

Name of the source file, or None if no file was given.

elements: dict

Mapping of integer index to MCQuestion or MCGroup objects in source order.

answer_key: dict

Deep copy of elements with correct options wrapped in \hl{}.

mc_answer_letters: list of str

One entry per question (or sub-question). Each entry is a comma-separated string of correct-answer letter labels (e.g., '(b)').

question_count: int

Total number of individual questions, counting each sub-question within a group separately.

classmethod from_string(tex, correct_string='CORRECT', seed=None, source_path=None, filename_hint=None)

Builds an MCExam directly from a LaTeX string without a file on disk.

Parameters:
  • tex (str) – LaTeX source containing an mcquestions environment, or raw question content.

  • correct_string (str, optional) – Marker for the correct answer. Defaults to 'CORRECT'.

  • seed (int, optional) – Seed for the internal RNG. Defaults to None.

  • source_path (str, optional) – Path of the originating file, used to set self.filepath. Defaults to None.

  • filename_hint (str, optional) – Short filename to assign to self.filename. Defaults to None.

Returns:

A fully initialized MCExam instance.

Return type:

MCExam

print_exam()

Prints the content of the exam to the console.

Returns:

None

print_answer_key()

Prints the answer key for the exam to the console.

Returns:

None

show_duplicates()

Displays any duplicate answer options found across all exam questions.

Returns:

None

to_latex(key=False)

Returns the full LaTeX string for this exam without writing to disk.

Parameters:

key (bool, optional) – If True, return the answer key version. Defaults to False.

Returns:

Complete LaTeX source for the exam or answer key.

Return type:

str

export_exam(filename=None)

Exports the student exam to a LaTeX file.

Parameters:

filename (str, optional) – Destination path. Defaults to the original filename.

Returns:

The LaTeX string that was written.

Return type:

str

export_key(filename=None)

Exports the answer key with correct answers highlighted to a LaTeX file.

Parameters:

filename (str, optional) – Destination path. Defaults to the original filename with '_Key' appended before the extension.

Returns:

The LaTeX string that was written.

Return type:

str

export_mc_answers_to_text(filename=None, header_text=None, mc_start=1)

Exports the MC answer letters to a plain-text file. Each line contains a question number and its correct-answer letter, e.g. '1. (b)'.

Parameters:
  • filename (str, optional) – Destination path. Defaults to the original filename with '_MC_Answers.txt' appended before the extension.

  • header_text (str, optional) – A title line written at the top of the file, followed by a blank line. Defaults to None.

  • mc_start (int, optional) – The global question number assigned to the first MC question. Useful when MC questions do not start at question 1 in the overall exam. Defaults to 1.

Returns:

The text that was written to the file.

Return type:

str

shuffle_questions(filename=None, seed=None, shuffle_within_groups=True)

Returns a new exam with questions shuffled. When at least one standalone MCQuestion exists, one is always placed first; the remaining standalone questions and any MCGroup objects are then randomly interleaved. When the exam contains only MCGroup objects, all groups are shuffled without the forced-first-question step.

Parameters:
  • filename (str, optional) – Filename for the returned exam object. Defaults to the original stem with '_questions_shuffled.tex' appended.

  • seed (int, optional) – Random seed for reproducibility. Defaults to None.

  • shuffle_within_groups (bool, optional) – Whether to also shuffle questions within each MCGroup. Defaults to True.

Returns:

A new MCExam instance with shuffled questions.

Return type:

MCExam

shuffle_options(filename=None, seed=None)

Returns a new exam with answer options shuffled within each question. The \all and \none options always remain at the end because they are stored as flags and appended during export.

Parameters:
  • filename (str, optional) – Filename for the returned exam object. Defaults to the original stem with '_options_shuffled.tex' appended.

  • seed (int, optional) – Random seed for reproducibility. Defaults to None.

Returns:

A new MCExam instance with shuffled options.

Return type:

MCExam

shuffle_options_and_questions(filename=None, seed=None, shuffle_within_groups=True)

Returns a new exam with both options and questions shuffled.

Parameters:
  • filename (str, optional) – Filename for the returned exam object. Defaults to the original stem with '_options_shuffled.tex' appended.

  • seed (int, optional) – Random seed for reproducibility. Defaults to None.

  • shuffle_within_groups (bool, optional) – Whether to shuffle questions within groups. Defaults to True.

Returns:

A new MCExam instance with shuffled options and questions.

Return type:

MCExam

add_periods(include_equations=True)

Adds periods to the end of answer choice text throughout the exam.

Parameters:

include_equations (bool, optional) – Whether to add a period after trailing math expressions. Defaults to True.

Returns:

None

capitalize_first()

Capitalizes the first letter of each answer choice throughout the exam.

Returns:

None

set_seed(seed=None)

Sets the random seed for the exam’s internal random number generator.

Parameters:

seed (int, optional) – Seed value. Defaults to None.

Returns:

None

class exam.FRExam(filename=None)

Handles free-response exams using the \question[points] syntax. Reads a LaTeX file and parses all \question blocks into a list of question dicts. \input{} commands that reference files containing a \question token are expanded automatically; figure and TikZ inputs inside answer blocks are left untouched.

Parameters:

filename (str, optional) – Path to the LaTeX exam file. If provided, the file is read and parsed immediately. Defaults to None.

filepath: pathlib.Path

Resolved absolute path to the source file, or None if no file was given.

filename: str

Name of the source file, or None if no file was given.

questions: list of dict

List of parsed question dicts. Each dict has keys 'file' (source filename), 'points' (int or None), and 'text' (full LaTeX string for the question).

classmethod from_string(tex, source_path=None, filename_hint=None)

Builds an FRExam directly from a LaTeX string without a file on disk. When source_path is provided its parent directory is used to resolve any \input{} commands that reference sub-files containing a \question token.

Parameters:
  • tex (str) – LaTeX source containing free-response question content.

  • source_path (str, optional) – Path of the originating file, used to resolve relative \input{} paths. Defaults to None.

  • filename_hint (str, optional) – Short filename to assign to self.filename. Defaults to None.

Returns:

A fully initialized FRExam instance.

Return type:

FRExam

to_latex(key=False)

Returns the full LaTeX string for this free-response exam.

Parameters:

key (bool, optional) – If True, reveal answer environments. Defaults to False.

Returns:

Complete LaTeX source for the exam or answer key.

Return type:

str

export_exam(filename=None)

Exports the student exam version (answers hidden) to a LaTeX file.

Parameters:

filename (str, optional) – Destination path. Defaults to 'FR_Exam.tex' in the same directory as the source file.

Returns:

None

export_key(filename=None)

Exports the answer key version (answers revealed) to a LaTeX file.

Parameters:

filename (str, optional) – Destination path. Defaults to 'FR_Key.tex' in the same directory as the source file.

Returns:

None

reveal_answers(text=None)

Returns the exam text with \begin{answer}...\end{answer} blocks expanded.

Parameters:

text (str, optional) – LaTeX text to process. Defaults to the concatenated text of all stored questions.

Returns:

LaTeX text with answer environments expanded.

Return type:

str

summary(max_chars=80)

Prints a summary of all parsed free-response questions, showing the question number, point value, source file, and a short preview of the question text.

Parameters:

max_chars (int, optional) – Maximum number of characters to show in the question preview. Defaults to 80.

Returns:

None

class exam.Exam(filename, mc=None, fr=None, correct_string='CORRECT', seed=None)

Combines MCExam and FRExam content into a single LaTeX document. Auto-detects MC and FR sections from \input{} statements or inline environments. Pre-built MCExam and FRExam objects may be passed directly to bypass auto-detection.

Parameters:
  • filename (str) – Path to the main exam LaTeX file.

  • mc (MCExam, optional) – Pre-parsed multiple-choice exam. Defaults to None (auto-detect).

  • fr (FRExam, optional) – Pre-parsed free-response exam. Defaults to None (auto-detect).

  • correct_string (str, optional) – Marker for correct MC answers. Defaults to 'CORRECT'.

  • seed (int, optional) – Random seed for reproducibility. Defaults to None.

mc: MCExam or None

The multiple-choice portion of the exam.

fr: FRExam or None

The free-response portion of the exam.

shuffle_options(seed=None, filename=None)

Returns a new Exam with shuffled MC options, preserving FR questions.

Parameters:
  • seed (int, optional) – Random seed for reproducibility. Defaults to None.

  • filename (str, optional) – If provided, sets the base path for subsequent export_exam and export_key calls.

Returns:

A deep copy of this Exam with MC options shuffled.

Return type:

Exam

to_latex(key=False)

Returns the full LaTeX string for the combined MC and FR exam. Raises ValueError if the assembled output does not contain exactly one mcquestions and one frquestions environment.

Parameters:

key (bool, optional) – If True, produce the answer key version. Defaults to False.

Returns:

Complete LaTeX source for the exam or answer key.

Return type:

str

Raises:

ValueError – If an environment appears more or fewer than once.

export_exam(filename=None)

Exports the combined student exam (no answers, no key-only content) to a LaTeX file.

Parameters:

filename (str, optional) – Destination path. Defaults to the source filename with '_Exported' appended before the extension.

Returns:

None

export_key(filename=None)

Exports the combined instructor key (FR answers shown, key-only content included) to a LaTeX file.

Parameters:

filename (str, optional) – Destination path. Defaults to the source filename with '_Exported_Key' appended before the extension.

Returns:

None

export_mc_answers_to_text(filename=None, header_text=None)

Exports the MC answer letters to a plain-text file with correct question numbering, even when FR questions precede the MC section. Scans the assembled exam to determine whether frquestions appears before mcquestions, and if so counts the FR questions to compute the MC start number automatically.

Parameters:
  • filename (str, optional) – Destination path. Defaults to the source filename with '_MC_Answers.txt' appended before the extension.

  • header_text (str, optional) – A title line written at the top of the file, followed by a blank line. Defaults to None.

Returns:

The text that was written to the file, or None if there are no MC questions.

Return type:

str or None

summary()

Prints a short summary of the combined exam’s MC and FR content.

Returns:

None

verify_integrity(latex_text=None)

Runs basic consistency checks on the combined exam LaTeX. Verifies that each expected environment appears exactly once and that no unresolved \input statements remain.

Parameters:

latex_text (str, optional) – LaTeX text to check. Defaults to self.to_latex(key=False).

Returns:

True if all checks pass, False otherwise.

Return type:

bool