Use `from __future__ import annotations` in every module, enforced by ruff

オープン
#1,962 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
68/100
issue の種類
リファクタリング
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python
領域
tooling

調査の方向性

Start by reading the existing Ruff configuration and the exclusions for generated or vendored code. Run ruff check src/autobahn --select I002 --fix, format only the touched files, and review the resulting changes. Done means Ruff enforces the import and the Twisted, asyncio, import-smoke, and documentation-build checks in the issue pass.

索引モデルが issue の本文から書いたものです。

説明

Why

Twice now, a type annotation that is fine for type checkers broke import autobahn... at runtime
on CPython 3.11–3.13, and both times it shipped:

  • #1878: a string forward reference combined with | None ("ISecurityModule" | None) raised
    TypeError at class-definition time in autobahn.wamp.cryptosign.
  • #1955: ITransport | IProcessTransport raised TypeError in autobahn.twisted.util / .wamp,
    because zope.interface's InterfaceClass supports | only from 6.2 on (fixed by #1959).

Both happen because, before Python 3.14, annotations on module-level functions and classes are
evaluated eagerly when the def / class statement runs. Any expression in an annotation that
does not work at runtime on that Python, with those dependency versions, becomes an import error.
from __future__ import annotations (PEP 563) makes every annotation in the module a string that is
never evaluated at import time, which removes this whole class of failure rather than one instance.

#1955 already named this as the complementary measure to the fix.

Current state (master ca1e60c7)

  • 7 modules under src/autobahn have the import; #1959 adds 2 more.
  • ruff check src/autobahn --select I002 with required-imports = ["from __future__ import annotations"]
    reports 91 files without it (39 of them test modules). Generated and vendored code is already
    excluded by the existing ruff config (src/autobahn/wamp/gen/*, src/autobahn/flatbuffers/*,
    src/autobahn/wamp/message_fbs.py).

Change

  1. Enforce it, so it stays consistent without anyone remembering:

    [tool.ruff.lint]
    extend-select = ["I002"]
    
    [tool.ruff.lint.isort]
    required-imports = ["from __future__ import annotations"]
    
  2. Apply it once, mechanically: ruff check src/autobahn --select I002 --fix, then ruff format
    on the touched files. I002 inserts the import without the blank line after it, which the
    formatter adds.

Is it safe?

Trial on a scratch copy of master, CPython 3.14: the import inserted into all 91 files, then both
suites run:

  • just test-twisted cpy314: PASSED (skips=32, successes=325)
  • just test-asyncio cpy314: 275 passed, 6 skipped
  • test_import_all.py: all passed

Why it should be safe in general:

  • The only place autobahn reads annotations at runtime is the check_types type check
    (ApplicationSession.type_check in autobahn/wamp/protocol.py). It reads the annotations of the
    user's registered functions, not of autobahn's own modules, so this change does not affect
    it. (Related, separate issue below.)
  • No name becomes unavailable: every name used in an annotation today is imported at runtime,
    because the annotation is currently evaluated. Code that later calls typing.get_type_hints()
    on autobahn classes resolves the strings against the same module globals.
  • On Python 3.14, annotation evaluation is deferred natively (PEP 649 / PEP 749) and the
    __future__ import keeps working. When autobahn's minimum becomes 3.14, the import can be
    dropped again; the ruff setting then goes with it.

Also to check in the PR: the documentation build (Sphinx autodoc renders the string annotations).

Out of scope

  • The pre-existing ruff format drift: with the current floating ruff (0.16.10),
    ruff format --check src/autobahn already reports 42 files on master. That is a separate,
    tool-drift matter; this change should only format the lines it touches.
  • Related latent bug, for its own issue: type_check uses func.__annotations__ directly and
    compares with isinstance(value, annotation). In a user module that itself uses
    from __future__ import annotations (or any string annotation), those are strings, and the check
    fails. It should resolve them, e.g. via typing.get_type_hints(func) or
    inspect.get_annotations(func, eval_str=True).

Acceptance

  • Every module under src/autobahn (except generated/vendored code) starts with
    from __future__ import annotations.
  • ruff enforces it (I002), so a new module without it fails just check-format.
  • Twisted and asyncio test suites, the import smoke tests (including the lowest-direct job from
    #1959) and the docs build are green.

Note: This issue was drafted with AI assistance (Claude Code).

主要言語
Python
スター
2.5k
フォーク
766
平均マージ
12時間 40分
マージ済み PR(30日)
20

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

crossbario/autobahn-python のほかの issue

crossbario/autobahn-python の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。