Skip to content

fix: show a clear failure when type_hints1 lacks a module annotation #63

Description

@abhiksark

Summary

The initial state of type_hints1 raises a raw NameError from its hidden check because a module does not define __annotations__ until it contains at least one annotation.

The exercise remains solvable, but the current failure is misleading for a learner. On the reported interpreter, Python also suggests __annotate__, which is an implementation detail and is not the requested solution.

This is a detailed follow-up to #56.

Reproduction

  1. Use a fresh Pythonlings workspace or reset type_hints1.

  2. Leave the starter declaration unchanged:

    count = 0
  3. Run:

    pythonlings run type_hints1

Actual result

The hidden check fails before it reaches its intended assertion message:

NameError: name '__annotations__' is not defined

The reporter's interpreter additionally suggests __annotate__.

Expected result

The incomplete exercise should fail with a learner-facing assertion such as:

AssertionError: count should be annotated as int

The intended edit should continue to pass:

count: int = 0

Root cause

checks/type_hints/type_hints1.py currently reads __annotations__ directly:

assert "count" in __annotations__, "count should have a type annotation"
assert __annotations__["count"] is int, "count should be annotated as int"

The runner executes the learner file and hidden check in one controlled namespace. Because the starter file contains no annotations, that namespace has no __annotations__ entry. The check therefore raises NameError before it can provide the intended guidance.

The other type-hint exercises inspect function-level __annotations__, which exists on their defined functions. The unsafe module-level lookup is isolated to type_hints1.

Proposed change

Handle the absent module annotation dictionary inside the affected hidden check:

annotations = globals().get("__annotations__", {})
assert annotations.get("count") is int, "count should be annotated as int"
print("type_hints1 ✓")

Keep the fix local to checks/type_hints/type_hints1.py. The shared runner should not create a synthetic __annotations__ value because the missing value is valid Python module behavior and only this check requires it.

Scope

  • Update checks/type_hints/type_hints1.py.
  • Preserve the learner exercise, reference solution, manifest order, and shared runner.
  • Add only the smallest regression coverage needed if existing curriculum verification does not exercise the incomplete starter state.

Acceptance criteria

  • count = 0 fails with AssertionError: count should be annotated as int, not NameError.
  • count: str = 0 fails with the same clear assertion.
  • count: int = 0 passes the hidden check.
  • Other type-hint exercises retain their current behavior.
  • The full test suite passes.
  • The passing curriculum verification passes.

Verification

The current failure was reproduced on Python 3.10.12 and Python 3.13.13. The proposed lookup was checked against the missing, incorrect, and correct annotation cases.

Run:

python -m pytest -q
pythonlings --root tests/fixtures/passing_curriculum verify

Roadmap alignment

This work advances the published roadmap item to continue auditing exercises for clearer hints and stronger hidden checks:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area: curriculumCurriculum exercises, checks, and solutionsbugSomething isn't workinggood first issueGood for newcomerssize: SSmall, focused contribution

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions