Skip to content

[patch] Defer Python annotations so a class can name itself or a later class - #158

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/102-python-forward-annotations
Oct 5, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/102-python-forward-annotations

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #102

What was wrong

Python before 3.14 evaluates annotations eagerly. A generated class whose own name, or the name of a class declared later in the file, appeared in a return type, parameter or field annotation therefore made the module raise NameError on import. #64 fixed the same problem for base lists only.

Change

  • PythonGenerator now overrides WriteFileDirectives and writes from __future__ import annotations as the first statement of a generated SourceFile. It goes after the header comment and before any import. A file with no members gets nothing.
  • Base lists keep quoting their forward references (PythonBaseFromGenericType), because a base is an expression and the future import does not defer it.
  • Updated the stale WriteFileDirectives remark in LanguageGeneratorBase, which said C++ was the only override even though Go already overrides it too.

Tests

  • New PythonGeneratedSourceImportsTests.AnnotationsNamingUndeclaredClasses_Import generates a module containing:

    • a static factory that returns its own class
    • a parameter typed as the declaring class
    • a field typed as the declaring class
    • a parameter typed as a class declared later in the file

    It then imports the module with a real interpreter and calls the factory.

  • Before the fix it failed under Python 3.11 with NameError: name 'Point' is not defined. With the fix it passes.

  • Full suite: 1055/1055 passed locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GQx1vbckMdZECPqnBTXWek


Generated by Claude Code

…r class

Python before 3.14 evaluates an annotation when the def or class body runs,
so a factory returning its own class, a parameter of the declaring type, a
field holding one, or a parameter naming a class declared further down made
the generated module raise NameError on import. The Python generator now
writes `from __future__ import annotations` as the file's first statement.

Fixes #102

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GQx1vbckMdZECPqnBTXWek
@sonarqubecloud

sonarqubecloud Bot commented Oct 5, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit bc2d133 into main Oct 5, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/102-python-forward-annotations branch October 6, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python output raises NameError on import when a method or field annotation names its own class (or a class declared later in the file)

2 participants