From a94710fdc60f261ae469fd9daccbe3e947e35f79 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Thu, 21 May 2026 18:16:09 +0200 Subject: [PATCH] refactor: drop from __future__ import annotations in Pydantic-defining files The project rule (CLAUDE.md, "Pydantic + from __future__ import annotations") bans the lazy-annotations import in files that define Pydantic Container or SSZModel classes, because lazy strings break model resolution for forward references. Eight audit-flagged files still carried it. Forward-reference fixes needed once annotations evaluate eagerly: - subtree.py: four classmethod constructors returning HashSubTree now annotated as Self (added from typing import Self). The methods are pure classmethod factories on the class itself, so Self is the cleanest fit and avoids quoting noise. - aggregation.py: five forward references to TypeOneMultiSignature and TypeTwoMultiSignature inside the class bodies became quoted strings, since the class isn't bound at the point those signatures are evaluated. Files whose future import alone was redundant (no forward refs): byte_arrays.py, bitfields.py, collections.py, ssz_base.py, container.py, xmss/containers.py. Audit's "Plus check" list (participation.py, validator.py, checkpoint.py) already did not carry the import. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lean_spec/subspecs/xmss/aggregation.py | 12 +++++------- src/lean_spec/subspecs/xmss/containers.py | 2 -- src/lean_spec/subspecs/xmss/subtree.py | 10 +++++----- src/lean_spec/types/bitfields.py | 2 -- src/lean_spec/types/byte_arrays.py | 2 -- src/lean_spec/types/collections.py | 2 -- src/lean_spec/types/container.py | 2 -- src/lean_spec/types/ssz_base.py | 2 -- 8 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/lean_spec/subspecs/xmss/aggregation.py b/src/lean_spec/subspecs/xmss/aggregation.py index 4df52745c..6b2ba0094 100644 --- a/src/lean_spec/subspecs/xmss/aggregation.py +++ b/src/lean_spec/subspecs/xmss/aggregation.py @@ -7,8 +7,6 @@ - Type-2: a merge of N Type-1 proofs over distinct messages. """ -from __future__ import annotations - from collections.abc import Sequence from lean_multisig_py import ( @@ -67,8 +65,8 @@ class TypeOneMultiSignature(Container): @staticmethod def select_greedily( - *proof_sets: set[TypeOneMultiSignature] | None, - ) -> tuple[list[TypeOneMultiSignature], set[ValidatorIndex]]: + *proof_sets: set["TypeOneMultiSignature"] | None, + ) -> tuple[list["TypeOneMultiSignature"], set[ValidatorIndex]]: """Greedy set-cover over Type-1 proofs to maximise validator coverage. Repeatedly selects the proof covering the most uncovered validators @@ -102,13 +100,13 @@ def select_greedily( @staticmethod def aggregate( - children: Sequence[tuple[TypeOneMultiSignature, Sequence[PublicKey]]], + children: Sequence[tuple["TypeOneMultiSignature", Sequence[PublicKey]]], raw_xmss: Sequence[tuple[PublicKey, Signature]], xmss_participants: AggregationBits | None, message: Bytes32, slot: Slot, mode: LeanEnvMode | None = None, - ) -> TypeOneMultiSignature: + ) -> "TypeOneMultiSignature": """Aggregate raw XMSS signatures and child Type-1 proofs into one Type-1 proof. Proof bytes are stored in compact no-pubkeys form. Participant identity is @@ -224,7 +222,7 @@ def aggregate( parts: Sequence[TypeOneMultiSignature], public_keys_per_part: Sequence[Sequence[PublicKey]] | None = None, mode: LeanEnvMode | None = None, - ) -> TypeTwoMultiSignature: + ) -> "TypeTwoMultiSignature": """Merge several Type-1 proofs (each over a distinct message) into one Type-2 proof. The returned Type-2 proof bytes are stored in compact no-pubkeys form. diff --git a/src/lean_spec/subspecs/xmss/containers.py b/src/lean_spec/subspecs/xmss/containers.py index 07198677f..02ec1f85e 100644 --- a/src/lean_spec/subspecs/xmss/containers.py +++ b/src/lean_spec/subspecs/xmss/containers.py @@ -1,7 +1,5 @@ """Generalized XMSS containers.""" -from __future__ import annotations - from typing import override from pydantic import field_serializer, field_validator, model_serializer diff --git a/src/lean_spec/subspecs/xmss/subtree.py b/src/lean_spec/subspecs/xmss/subtree.py index 22d1f9735..973e6e2e6 100644 --- a/src/lean_spec/subspecs/xmss/subtree.py +++ b/src/lean_spec/subspecs/xmss/subtree.py @@ -5,7 +5,7 @@ implementing the memory-efficient top-bottom tree traversal approach. """ -from __future__ import annotations +from typing import Self from lean_spec.types import Uint64 from lean_spec.types.container import Container @@ -103,7 +103,7 @@ def new( start_index: Uint64, parameter: Parameter, lowest_layer_nodes: list[HashDigestVector], - ) -> HashSubTree: + ) -> Self: """ Builds a new sparse Merkle subtree starting from a specified layer. @@ -187,7 +187,7 @@ def new_top_tree( start_bottom_tree_index: Uint64, parameter: Parameter, bottom_tree_roots: list[HashDigestVector], - ) -> HashSubTree: + ) -> Self: """ Constructs a top tree from the roots of bottom trees. @@ -243,7 +243,7 @@ def new_bottom_tree( bottom_tree_index: Uint64, parameter: Parameter, leaves: list[HashDigestVector], - ) -> HashSubTree: + ) -> Self: """ Constructs a single bottom tree from leaf hashes. @@ -327,7 +327,7 @@ def from_prf_key( prf_key: PRFKey, bottom_tree_index: Uint64, parameter: Parameter, - ) -> HashSubTree: + ) -> Self: """ Generates a single bottom tree on-demand from the PRF key. diff --git a/src/lean_spec/types/bitfields.py b/src/lean_spec/types/bitfields.py index 0c2f2c071..169c19107 100644 --- a/src/lean_spec/types/bitfields.py +++ b/src/lean_spec/types/bitfields.py @@ -12,8 +12,6 @@ Bit i of the input lands in byte i // 8 at position i % 8. """ -from __future__ import annotations - import math from collections.abc import Sequence from typing import ( diff --git a/src/lean_spec/types/byte_arrays.py b/src/lean_spec/types/byte_arrays.py index 82f197582..c59b27475 100644 --- a/src/lean_spec/types/byte_arrays.py +++ b/src/lean_spec/types/byte_arrays.py @@ -11,8 +11,6 @@ Both flavors serialize as the raw bytes themselves — no length prefix, no delimiter. """ -from __future__ import annotations - from collections.abc import Iterable from typing import IO, Any, ClassVar, Self, override diff --git a/src/lean_spec/types/collections.py b/src/lean_spec/types/collections.py index 26350bcf9..2446a8b32 100644 --- a/src/lean_spec/types/collections.py +++ b/src/lean_spec/types/collections.py @@ -1,7 +1,5 @@ """Vector and List Type Specifications.""" -from __future__ import annotations - import io from collections.abc import Iterator, Sequence from typing import ( diff --git a/src/lean_spec/types/container.py b/src/lean_spec/types/container.py index 9c6e9b1b8..3f0718ea4 100644 --- a/src/lean_spec/types/container.py +++ b/src/lean_spec/types/container.py @@ -7,8 +7,6 @@ Ethereum's serialization format. """ -from __future__ import annotations - from typing import IO, Any, Self, override from .constants import OFFSET_BYTE_LENGTH diff --git a/src/lean_spec/types/ssz_base.py b/src/lean_spec/types/ssz_base.py index 222e8b970..92b9fc905 100644 --- a/src/lean_spec/types/ssz_base.py +++ b/src/lean_spec/types/ssz_base.py @@ -1,7 +1,5 @@ """Base classes and interfaces for all SSZ types.""" -from __future__ import annotations - import io from abc import ABC, abstractmethod from collections.abc import Sequence