Skip to content

refactor(testing): attach filler plugin state via typed StashKeys - #908

Merged
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/filler-config-stash
Jun 10, 2026
Merged

refactor(testing): attach filler plugin state via typed StashKeys#908
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/filler-config-stash

Conversation

@tcoratger

Copy link
Copy Markdown
Collaborator

Motivation

The fill pytest plugin smuggled five attributes onto the pytest.Config object — the fixture collector, the selected fork class, and the per-test fixture path (absolute + relative) and format. Each write needed a # type: ignore[attribute-defined] (six in total), and each read used a hasattr(...) probe:

config.fixture_collector = FixtureCollector(...)   # type: ignore[attribute-defined]
config.test_fork_class = fork_class                # type: ignore[attribute-defined]
...
if hasattr(config, "test_fork_class"):
    fork_class = config.test_fork_class

This is monkey-patching the config with undeclared attributes — untyped, unchecked, and flagged by the type checker.

What this does

Stores the same state in config.stash, keyed by module-level StashKeys — the documented, type-safe mechanism for plugin state:

FIXTURE_COLLECTOR_KEY: pytest.StashKey[FixtureCollector] = pytest.StashKey()
TEST_FORK_CLASS_KEY: pytest.StashKey[type[BaseFork]] = pytest.StashKey()
FIXTURE_PATH_ABSOLUTE_KEY: pytest.StashKey[str] = pytest.StashKey()
FIXTURE_PATH_RELATIVE_KEY: pytest.StashKey[str] = pytest.StashKey()
FIXTURE_FORMAT_KEY: pytest.StashKey[str] = pytest.StashKey()

Result:

  • All six type: ignores removed. The collector reads back as FixtureCollector and the fork class as type[BaseFork] — fully typed.
  • All hasattr probes replaced with KEY in config.stash.
  • The fork class is resolved by membership + direct indexing (FORKS_BY_NAME[name]) so it is never Optional — the type checker does not narrow through the NoReturn CLI exit, and this keeps fork_class.name() / <= valid without an assert.

No behavior change: same data flow, same fixture output, same fork filtering and CLI error paths.

Testing

  • just check passes (lint, format, ty, codespell, mdformat) — zero type: ignore, zero hasattr(config...) left in the file.
  • Fill smoke: 118 SSZ fixtures generate and write to disk via the stashed collector; report paths attach correctly.
  • Invalid --fork still exits cleanly with the same message and lists available forks.

🤖 Generated with Claude Code

The fill plugin smuggled five attributes onto the pytest config object:
the fixture collector, the selected fork class, and the per-test fixture
path and format.
Each assignment needed a type: ignore for setting an undeclared attribute,
and each read used a hasattr probe, six ignores in total.

Store this state in config.stash keyed by module-level StashKeys instead.
The stash is the documented, type-safe place for plugin state, so the
collector reads back as a FixtureCollector and the fork class as
type[BaseFork] with no ignores, and presence checks use "in" on the stash.

Resolve the fork class by membership and direct indexing so it is never
optional, since the type checker does not narrow through the NoReturn exit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tcoratger
tcoratger merged commit 4c8a7eb into leanEthereum:main Jun 10, 2026
13 checks passed
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