Skip to content

refactor(client): split event_source.py into a package#687

Merged
tcoratger merged 1 commit intoleanEthereum:mainfrom
tcoratger:refactor/event-source-split
Apr 27, 2026
Merged

refactor(client): split event_source.py into a package#687
tcoratger merged 1 commit intoleanEthereum:mainfrom
tcoratger:refactor/event-source-split

Conversation

@tcoratger
Copy link
Copy Markdown
Collaborator

Summary

Splits the single 1422-line event_source.py into a small package with three focused modules. Pure reorganization: every existing docstring and inline comment is preserved verbatim from main, no behavior changes, no external import path moves, no test file touched.

New layout

src/lean_spec/subspecs/networking/client/event_source/
├── __init__.py    — package re-exports only
├── protocol.py    — EventSource Protocol, GossipMessageError, SUPPORTED_PROTOCOLS
├── gossip.py      — GossipHandler + read_gossip_message (wire-format parser)
└── live.py        — LiveNetworkEventSource (the orchestrator)

Dependency direction is strict and one-way: protocol → gossip → live. The __init__.py re-exports the full public surface (LiveNetworkEventSource, EventSource, GossipHandler, GossipMessageError, SUPPORTED_PROTOCOLS, read_gossip_message) so every existing from lean_spec.subspecs.networking.client.event_source import … keeps working unchanged. Re-exports through a package __init__ are not back-compat shims — they are the standard Python way to surface a package API.

Two structural cleanups inside live.py

_accept_streams (243 lines, three nested concerns) decomposed into helper methods on LiveNetworkEventSource:

  • _negotiate_inbound_stream — multistream-select; returns (protocol_id, wrapper) or None on failure.
  • _handle_gossipsub_inbound_stream — registers the inbound gossipsub stream and arms outbound setup.
  • _setup_outbound_gossipsub_after_delay — was a nested closure inside _accept_streams; now a real method, no captured state.
  • _handle_reqresp_inbound_stream — schedules the reqresp server task.

The orchestrator becomes ~30 lines: accept loop, protocol-id dispatch, outer error handling.

Two byte-identical inbound handlers collapsed. _handle_inbound_quic_connection and _handle_inbound_connection differed only in one gs_id log prefix on the QUIC variant. The unified _handle_inbound_connection survives; _listen_quic now passes it as the QUIC manager's connection callback. The dropped gs_id prefix added no debug signal that peer_id does not already provide.

Documentation policy

Every existing docstring and inline comment is byte-for-byte identical to main. Module-level preamble that referenced gossip-only material (GOSSIP MESSAGE FORMAT, MESSAGE DEDUPLICATION) moves to gossip.py's module docstring; the rest stays where it was. The four newly-extracted methods have minimal docstrings describing their parameters and return values.

Test plan

  • uvx tox -e all-checks (ruff, format, ty, codespell, mdformat) — pass.
  • uv run pytest tests/lean_spec/subspecs/networking/client tests/lean_spec/subspecs/networking/gossipsub/test_gossipsub.py — 159 passed in 0.28s.
  • Reviewer to spot-check that no docstring or inline comment was rewritten.
  • Reviewer to spot-check the _accept_streams decomposition preserves the original ordering and error handling.

🤖 Generated with Claude Code

The single 1422-line event_source.py grew to mix three concerns: the
abstract event-source contract, the inbound gossip wire-format parser,
and the live network orchestrator. This PR splits it into a focused
package without rewriting any documentation or changing any behavior.

New layout:

- event_source/protocol.py: EventSource Protocol, GossipMessageError,
  SUPPORTED_PROTOCOLS allow-list (the dependency-light shared surface).
- event_source/gossip.py: GossipHandler and read_gossip_message (the
  inbound gossipsub wire-format parser).
- event_source/live.py: LiveNetworkEventSource (the orchestrator that
  owns connections, streams, and the gossipsub behavior).
- event_source/__init__.py: re-exports the full public surface so every
  existing import path keeps working unchanged.

Dependency direction: protocol -> gossip -> live, strict and one-way.

Inside live.py, two structural cleanups:

- _accept_streams (243 lines, three nested concerns) decomposes into
  _negotiate_inbound_stream, _handle_gossipsub_inbound_stream,
  _setup_outbound_gossipsub_after_delay (was a nested closure), and
  _handle_reqresp_inbound_stream. The orchestrator becomes ~30 lines:
  accept loop plus protocol-id dispatch.
- _handle_inbound_quic_connection collapses into _handle_inbound_connection
  (the two were byte-identical except for one log line). _listen_quic
  now passes the unified handler.

Every existing docstring and inline comment is preserved verbatim from
main; only the structural pieces above changed. No external import path
moves; no test file is touched.

Verified:

- uvx tox -e all-checks (ruff, format, ty, codespell, mdformat) passes.
- tests/lean_spec/subspecs/networking/client and gossipsub tests
  (159 cases) pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tcoratger tcoratger merged commit 8183052 into leanEthereum:main Apr 27, 2026
13 checks passed
tcoratger added a commit to tcoratger/leanSpec that referenced this pull request Apr 27, 2026
Absorbs PR leanEthereum#687 which split event_source.py into a package.

Resolves one content conflict in event_source/live.py:
- Kept the forks.devnet4.containers import paths from this branch.
- Accepted upstream's removal of the snappy import (decompress usage
  moved to event_source/gossip.py during the split, so live.py no
  longer needs it).

Reroutes the new event_source/gossip.py file's stale
subspecs.containers imports to forks.devnet4.containers (rename-vs-add
auto-merge took the file as-is from upstream).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant