Code Standards¶
This page outlines the code standards used in ethereum/execution-specs. Many of the following preferences are enforced in CI via static code checks which can be ran locally via:
just static
See Verifying Changes for more details on running checks locally and ensuring that your code passes CI checks.
Python Coding Preferences¶
- Line Length: 79 characters maximum.
- Formatting: Enforced by
ruff(similar toblack). Runjust fixto format code viaruff. - Documentation: All public functions and classes should have docstrings:
- Docstrings should have a good one-line summary which uses the imperative ("Return" not "Returns").
- Add a blank line after the summary for multi-line docstrings.
- Single-line docstrings should have triple quotes on the same line.
- Imports: Use explicit imports (no
from module import *). - Relative Imports: Use relative imports within the same package.
- Error Handling: Use explicit exception types and meaningful error messages.
- Type Hints: All functions should include type annotations.
- Unused Function Arguments: When unavoidable, use
del, e.g.,del unused_var, at function start to avoid flagging linter errors. - Variable Naming:
- Use
snake_casefor variables, functions, and modules. - Use
PascalCasefor classes. - Use
UPPER_CASEfor constants.
- Use
- File Paths: Strongly prefer
pathliboveros.pathfor file system operations. - Retry Logic: Use
tenacitylibrary for handling flaky network connections and transient failures.
Testing Framework Plugins with Pytester¶
Use pytest's pytester fixture when writing tests for our pytest plugins and CLI commands.
runpytest() is the default. It runs the inner session in-process, is fast, and gives access to helpers like assert_outcomes() and fnmatch_lines().
runpytest_subprocess() runs the inner session in a separate process. Use it only when in-process mode causes state leakage (e.g., Pydantic ModelMetaclass cache pollution or global mutation in pytest_configure). Subprocess isolation masks these bugs rather than fixing them, so prefer fixing the root cause and use subprocess mode as defense-in-depth.
Don't use raw subprocess.run() in pytester-based tests. If you need process isolation, use runpytest_subprocess().
Both methods return a RunResult with .ret, .outlines, .errlines, assert_outcomes(), and fnmatch_lines(). When the inner test is expected to fail, use capsys.readouterr() after runpytest_subprocess() to suppress the inner failure output that pytester replays to stdout.