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
-
Use a fresh Pythonlings workspace or reset type_hints1.
-
Leave the starter declaration unchanged:
-
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:
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:
Summary
The initial state of
type_hints1raises a rawNameErrorfrom 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
Use a fresh Pythonlings workspace or reset
type_hints1.Leave the starter declaration unchanged:
Run:
pythonlings run type_hints1Actual result
The hidden check fails before it reaches its intended assertion message:
The reporter's interpreter additionally suggests
__annotate__.Expected result
The incomplete exercise should fail with a learner-facing assertion such as:
The intended edit should continue to pass:
Root cause
checks/type_hints/type_hints1.pycurrently reads__annotations__directly: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 raisesNameErrorbefore 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 totype_hints1.Proposed change
Handle the absent module annotation dictionary inside the affected hidden check:
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
checks/type_hints/type_hints1.py.Acceptance criteria
count = 0fails withAssertionError: count should be annotated as int, notNameError.count: str = 0fails with the same clear assertion.count: int = 0passes the hidden check.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:
Roadmap alignment
This work advances the published roadmap item to continue auditing exercises for clearer hints and stronger hidden checks: