Skip to content

Commit 3595f4e

Browse files
authored
Merge pull request RustPython#1730 from youknowone/type-error
Fix type() error message and BaseException.__str__
2 parents e46d38e + c366c20 commit 3595f4e

File tree

4 files changed

+33
-10
lines changed

4 files changed

+33
-10
lines changed

Lib/test/test_types.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,8 +1169,6 @@ def __prepare__(mcls, name, bases):
11691169
with self.assertRaises(TypeError):
11701170
X = types.new_class("X", (int(), C))
11711171

1172-
# TODO: RUSTPYTHON
1173-
@unittest.expectedFailure
11741172
def test_one_argument_type(self):
11751173
expected_message = 'type.__new__() takes exactly 3 arguments (1 given)'
11761174

tests/snippets/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ def round_trip_repr(e):
1515
assert str(exc) == "'message'"
1616
assert round_trip_repr(exc)
1717

18+
assert LookupError.__str__(exc) == "message"
19+
1820
exc = KeyError('message', 'another message')
1921
assert str(exc) == "('message', 'another message')"
2022
assert round_trip_repr(exc)

vm/src/exceptions.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ impl PyBaseException {
131131

132132
#[pymethod(name = "__str__")]
133133
fn str(&self, vm: &VirtualMachine) -> PyStringRef {
134-
let str_args = exception_args_as_string(vm, self.args(), false);
134+
let str_args = exception_args_as_string(vm, self.args(), true);
135135
match str_args.into_iter().exactly_one() {
136136
Err(i) if i.len() == 0 => PyString::from("").into_ref(vm),
137137
Ok(s) => s,
@@ -616,6 +616,18 @@ fn make_arg_getter(idx: usize) -> impl Fn(PyBaseExceptionRef, &VirtualMachine) -
616616
}
617617
}
618618

619+
fn key_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyStringRef {
620+
let args = exc.args();
621+
if args.as_slice().len() == 1 {
622+
exception_args_as_string(vm, args, false)
623+
.into_iter()
624+
.exactly_one()
625+
.unwrap()
626+
} else {
627+
exc.str(vm)
628+
}
629+
}
630+
619631
pub fn init(ctx: &PyContext) {
620632
let excs = &ctx.exceptions;
621633

@@ -638,6 +650,10 @@ pub fn init(ctx: &PyContext) {
638650
"value" => ctx.new_property(make_arg_getter(0)),
639651
});
640652

653+
extend_class!(ctx, &excs.key_error, {
654+
"__str__" => ctx.new_method(key_error_str),
655+
});
656+
641657
extend_class!(ctx, &excs.unicode_decode_error, {
642658
"encoding" => ctx.new_property(make_arg_getter(0)),
643659
"object" => ctx.new_property(make_arg_getter(1)),

vm/src/obj/objtype.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,20 @@ impl PyClassRef {
254254
fn tp_new(metatype: PyClassRef, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
255255
vm_trace!("type.__new__ {:?}", args);
256256

257-
if metatype.is(&vm.ctx.types.type_type) {
258-
if args.args.len() == 1 && args.kwargs.is_empty() {
259-
return Ok(args.args[0].class().into_object());
260-
}
261-
if args.args.len() != 3 {
262-
return Err(vm.new_type_error("type() takes 1 or 3 arguments".to_string()));
263-
}
257+
let is_type_type = metatype.is(&vm.ctx.types.type_type);
258+
if is_type_type && args.args.len() == 1 && args.kwargs.is_empty() {
259+
return Ok(args.args[0].class().into_object());
260+
}
261+
262+
if args.args.len() != 3 {
263+
return Err(vm.new_type_error(if is_type_type {
264+
"type() takes 1 or 3 arguments".to_string()
265+
} else {
266+
format!(
267+
"type.__new__() takes exactly 3 arguments ({} given)",
268+
args.args.len()
269+
)
270+
}));
264271
}
265272

266273
let (name, bases, dict): (PyStringRef, PyIterable<PyClassRef>, PyDictRef) =

0 commit comments

Comments
 (0)