Parity
gopy is a behavioural twin of CPython. The line that defines
behavioural parity is intentionally tight: every observable side
effect should match. That includes return values, exception types,
exception messages, bytecode emitted, location columns, .pyc
output, and the order in which side effects happen.
How parity is enforced
Function-level translation
Every Go function under gopy has a // CPython: citation pointing
to the C function it ports. Reviewers reject patches that add
helper functions without a CPython counterpart, because divergence
starts with one extra abstraction.
// CPython: Python/compile.c:L353 _PyAST_Compile
func Compile(mod ast.Mod, filename string, optimize int) (*Code, error) {
// ...
}
Unit tests with golden fixtures
Each subsystem has a corpus of fixtures stored as .py input with
golden output: tokens, AST dumps, disassemblies, .pyc bytes,
program stdout. The fixture is generated once from CPython, then
gopy is required to reproduce it byte for byte.
Parity tests
parser/parity_test.go, compile/compiler_test.go, and
vm/eval_test.go re-run a curated set of programs against both
gopy and CPython at test time, then diff the results. Anything
that differs is a parity bug.
The Python test suite
The Lib/test/ directory from CPython is vendored under
stdlib/test/. The runner under v05test/ walks that tree and
checks pass / fail against the upstream expected status. The
sweep is the truth of record for parity at the language level.
Where the bar is
Behaviour that is documented in the language reference is load-bearing: same value, same type, same message. Behaviour that the language reference calls implementation-defined still has to match CPython on byte-equal output unless the spec explicitly says the result is unspecified.
CPython implementation details with no Python-visible behaviour
(internal allocation strategy, header layout, the precise
addresses returned by id) do not need to match.
What changes when there is a mismatch
Bug in gopy. Fix gopy.
The only carve-out is the surface API style. Go callers see Go
idioms (interface satisfaction over duck-typing, error returns,
package layout that follows the Go standard library). The
Python-visible behaviour is unaffected.
Reporting a parity bug
A useful bug report has three parts:
- Source. Minimal Python that reproduces the mismatch.
- CPython output. What
python3(3.14.x) produces. - gopy output. What
gopyproduces from the same source.
Open the issue at github.com/tamnd/gopy/issues with all three. Tracebacks, return values, exception messages, and bytecode diffs all qualify.
How a parity port lands
The typical flow for porting a CPython subsystem to gopy:
- Pin the CPython source. The work targets a specific
3.14.x tag in a local
~/cpython-314mirror. - Function-by-function translation. Each Go function gets
a
// CPython: file.c:Lnn FuncNamecitation. No invented shims. - Golden corpus. A test corpus is generated from CPython and frozen as the expected output.
- Spec entry. The work has an entry under website/docs/specs tracking the checklist of functions ported, tests passing, and remaining gaps.
- CI gate. The spec's checklist promotes from "in progress" to "shipped" only when the gate test passes against the golden corpus.
This is slower than freehand reimplementation, but it is the only way to keep behaviour aligned across hundreds of files.