Skip to content

Commit 75a7646

Browse files
committed
Let the bool format answer with the error its value raised
`pack_single()` leaves `'?'` to `PyObject_IsTrue()` and returns what that raised. Packing classified the error instead, so a `ValueError` from a `__bool__` came back as "memoryview: invalid value for format '?'". Assisted-by: Claude
1 parent aa525fa commit 75a7646

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

‎crates/vm/src/buffer.rs‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ impl PackError {
6161
};
6262
Self { kind, exception }
6363
}
64+
65+
/// An error that is the answer exactly as it was raised. `pack_single()`
66+
/// leaves `'?'` to `PyObject_IsTrue()` this way, with no message of its own.
67+
fn raised(exception: PyBaseExceptionRef) -> Self {
68+
Self {
69+
kind: PackErrorKind::Raised,
70+
exception,
71+
}
72+
}
6473
}
6574

6675
static OVERFLOW_MSG: &str = "total struct size too long"; // not a const to reduce code size
@@ -803,7 +812,7 @@ impl Packable for bool {
803812
data: &mut [u8],
804813
) -> Result<(), PackError> {
805814
let v = ArgIntoBool::try_from_object(vm, arg)
806-
.map_err(|e| PackError::from_exception(e, vm))?
815+
.map_err(PackError::raised)?
807816
.into_bool() as u8;
808817
v.pack_int::<E>(data);
809818
Ok(())

‎extra_tests/snippets/builtin_memoryview.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,3 +764,25 @@ def test_delete_answers_readonly_first():
764764
test_setitem_error_kinds()
765765
test_setitem_propagates_index_errors()
766766
test_delete_answers_readonly_first()
767+
768+
769+
def test_bool_format_keeps_its_own_error():
770+
# Deciding truth is the value's own code, and what it raises is the answer.
771+
class Raises:
772+
def __init__(self, exc):
773+
self.exc = exc
774+
775+
def __bool__(self):
776+
raise self.exc
777+
778+
view = memoryview(bytearray(b"\x00")).cast("?")
779+
for exc in (ZeroDivisionError("boom"), ValueError("nope"), TypeError("nah")):
780+
try:
781+
view[0] = Raises(exc)
782+
except type(exc) as e:
783+
assert str(e) == str(exc), e
784+
else:
785+
raise AssertionError(f"expected {type(exc).__name__}")
786+
787+
788+
test_bool_format_keeps_its_own_error()

0 commit comments

Comments
 (0)