Deferred by #197 (the fix for #188). Filed so the deferral has a home rather
than evaporating when #188 closes.
What #197 does, and where it stops
#197 drops partspec's own frames from a traceback when a contract raises,
keeping the user's. It deliberately bails to the unfiltered traceback for
chained exceptions — raise X from Y, and the implicit __context__ chain a
bare raise inside an except block produces.
The reasoning is sound and should be preserved if this is ever picked up:
per-segment filtering means walking the chain and re-emitting CPython's
connector prose (The above exception was the direct cause of the following exception: / During handling of the above exception, another exception occurred:) and the +-+---- 1 ---- group tree by hand. Get a
connector wrong and the output asserts a causal relation that did not happen.
A noisy true trace beats a tidy false one, in a tool whose thesis is that
silence must never read as success.
How big is the affected class?
Smaller than it first appears. Measured across all 21 shipped contract files
(examples/*/*.py, evals/cases*/*/spec.py,
evals/baseline-20260806/*/spec.py):
try:/except occurrences: 1 — and it is the word "except" inside a
docstring
raise occurrences: 0
ContractError appears in no example or skill; it occurs only in
docs/SPEC-contract.md, twice, both describing what partspec raises. An AST
sweep of src/partspec/ found zero except: handlers that re-raise
without from, so partspec never manufactures an implicit chain itself.
So try/except → raise ContractError(...) is an idiomatic pattern in
principle but not one this repo's own corpus exhibits. That is an argument for
leaving it deferred, not for closing it — the corpus is our code, and the
users #188 was filed by are not us.
If picked up
Filter each segment of the chain independently while reproducing CPython's
connectors exactly, rather than hand-rolling them. traceback.TracebackException
walks the chain structurally and may make this tractable without string
surgery. Any implementation needs tests for: explicit from, implicit
__context__, from None (__suppress_context__), and a chain whose
segments are themselves ExceptionGroups.
Deferred by #197 (the fix for #188). Filed so the deferral has a home rather
than evaporating when #188 closes.
What #197 does, and where it stops
#197 drops partspec's own frames from a traceback when a contract raises,
keeping the user's. It deliberately bails to the unfiltered traceback for
chained exceptions —
raise X from Y, and the implicit__context__chain abare
raiseinside anexceptblock produces.The reasoning is sound and should be preserved if this is ever picked up:
per-segment filtering means walking the chain and re-emitting CPython's
connector prose (
The above exception was the direct cause of the following exception:/During handling of the above exception, another exception occurred:) and the+-+---- 1 ----group tree by hand. Get aconnector wrong and the output asserts a causal relation that did not happen.
A noisy true trace beats a tidy false one, in a tool whose thesis is that
silence must never read as success.
How big is the affected class?
Smaller than it first appears. Measured across all 21 shipped contract files
(
examples/*/*.py,evals/cases*/*/spec.py,evals/baseline-20260806/*/spec.py):try:/exceptoccurrences: 1 — and it is the word "except" inside adocstring
raiseoccurrences: 0ContractErrorappears in no example or skill; it occurs only indocs/SPEC-contract.md, twice, both describing what partspec raises. An ASTsweep of
src/partspec/found zeroexcept:handlers that re-raisewithout
from, so partspec never manufactures an implicit chain itself.So
try/except → raise ContractError(...)is an idiomatic pattern inprinciple but not one this repo's own corpus exhibits. That is an argument for
leaving it deferred, not for closing it — the corpus is our code, and the
users #188 was filed by are not us.
If picked up
Filter each segment of the chain independently while reproducing CPython's
connectors exactly, rather than hand-rolling them.
traceback.TracebackExceptionwalks the chain structurally and may make this tractable without string
surgery. Any implementation needs tests for: explicit
from, implicit__context__,from None(__suppress_context__), and a chain whosesegments are themselves
ExceptionGroups.