diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py index 11e2abb82c5..0dd92c93396 100644 --- a/Lib/test/test_str.py +++ b/Lib/test/test_str.py @@ -2414,7 +2414,6 @@ def test_ucs4(self): else: self.fail("Should have raised UnicodeDecodeError") - @unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: is not def test_conversion(self): # Make sure __str__() works properly class StrWithStr(str): diff --git a/crates/vm/src/builtins/str.rs b/crates/vm/src/builtins/str.rs index 8707c5cf769..59b4145c75a 100644 --- a/crates/vm/src/builtins/str.rs +++ b/crates/vm/src/builtins/str.rs @@ -394,13 +394,10 @@ impl Constructor for PyStr { type Args = StrArgs; fn slot_new(cls: PyTypeRef, func_args: FuncArgs, vm: &VirtualMachine) -> PyResult { - // Optimization: return exact str as-is (only when no encoding/errors provided) - if cls.is(vm.ctx.types.str_type) - && func_args.args.len() == 1 - && func_args.kwargs.is_empty() - && func_args.args[0].class().is(vm.ctx.types.str_type) + // Optimization: for exact str, return PyObject_Str result as-is + if cls.is(vm.ctx.types.str_type) && func_args.args.len() == 1 && func_args.kwargs.is_empty() { - return Ok(func_args.args[0].clone()); + return func_args.args[0].str(vm).map(Into::into); } let args: Self::Args = func_args.bind(vm)?; diff --git a/extra_tests/snippets/builtin_str_subclass.py b/extra_tests/snippets/builtin_str_subclass.py index 73e23615c4d..4e1f6080715 100644 --- a/extra_tests/snippets/builtin_str_subclass.py +++ b/extra_tests/snippets/builtin_str_subclass.py @@ -19,6 +19,33 @@ def __init__(self, value): assert y + " other" == "1 other" assert y.x == "substr" + +class ReprStrSubclass(str): + pass + + +class WithStr: + def __init__(self, value): + self.value = value + + def __str__(self): + return self.value + + +class WithRepr: + def __init__(self, value): + self.value = value + + def __repr__(self): + return self.value + + +str_value = ReprStrSubclass("abc") +assert str(WithStr(str_value)) is str_value + +repr_value = ReprStrSubclass("") +assert str(WithRepr(repr_value)) is repr_value + ## Base strings currently get an attribute dict, but shouldn't. # with assert_raises(AttributeError): # "hello".x = 5