fix(scripts): make cocotb_ref_model importable again - #1589
Conversation
The module fails at import:
NameError: name 'EvalContext' is not defined
EvalContext is annotated on function parameters at lines 174 and 215 but the class
is defined at line 402. Python evaluates annotations at function-definition time
unless the module opts out, so the forward reference raises before argparse is
reached and the tool cannot run at all.
Adding `from __future__ import annotations` defers annotation evaluation and the
module loads. Afterwards it reaches its own argument parser and reports what it
needs:
usage: cocotb_ref_model.py [-h] --ast-json AST_JSON --verilog VERILOG
--top-module TOP_MODULE [--use-cocotb] [--verbose]
Placement matters and is easy to get wrong: a __future__ import may be preceded
only by the module docstring, comments and blank lines. Inserting it between the
shebang and the docstring also makes the module load, but silently demotes the
docstring to an ordinary string expression and leaves __doc__ as None. It is
inserted after the docstring here, and ast.get_docstring confirms the docstring
survives.
Found by extending the pass-57/58 side-effect sweep to the EXEC bucket -- the last
12 scripts in the repository that had never been executed. No workflow references
this file, which is why the breakage went unnoticed.
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
now-sync-gate requires every PR to master to update docs/NOW.md. This PR predates my knowing that; the entry describes what it lands and states its honesty limits, in the file's existing shape.
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
PR DashboardGenerated at: 2026-08-01 07:44:48 UTC
Summary
Seal Status
|
Five branches each added an entry at the top of docs/NOW.md, so the first merge conflicted with the other four. Resolved losslessly: this branch's entry sits on top of master's file as it now stands.
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
PR DashboardGenerated at: 2026-08-01 07:48:14 UTC
Summary
Seal Status
|
Every PR here must touch docs/NOW.md and every entry goes at the top, so each merge conflicts whatever is still open. Resolved losslessly: this branch's entry sits on top of master's file as it now stands.
PR DashboardGenerated at: 2026-08-01 08:00:49 UTC
Summary
Seal Status
|
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Every PR here must touch docs/NOW.md and every entry goes at the top, so each merge conflicts whatever is still open. Resolved losslessly.
PR DashboardGenerated at: 2026-08-01 08:02:12 UTC
Summary
Seal Status
|
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Every PR here must touch docs/NOW.md and every entry goes at the top, so each merge conflicts whatever is still open.
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
PR DashboardGenerated at: 2026-08-01 08:05:29 UTC
Summary
Seal Status
|
scripts/cocotb_ref_model.pyfails at import:EvalContextis used as a parameter annotation at lines 174 and 215; the class is defined at line 402. Python evaluates annotations at function-definition time unless the module opts out, so the forward reference raises before argparse runs and the tool cannot be invoked at all.from __future__ import annotationsdefers annotation evaluation. After it the module loads and reaches its own parser:Placement matters. A
__future__import may be preceded only by the module docstring, comments and blank lines. Putting it between the shebang and the docstring also makes the module load — but silently demotes the docstring to an ordinary string expression, leaving__doc__asNone. It goes after the docstring here, andast.get_docstringconfirms the docstring survives.Found by extending the side-effect sweep of #1581 to the EXEC bucket — the last 12 scripts in the repository that had never been executed. No workflow references this file, which is why the breakage went unnoticed.
Closes #1592