Preserve str subclass type returned by __str__ / __repr__#7701
Conversation
Closes RustPython#7450. CPython's unicode_new_impl returns the PyObject_Str result as-is when type == &PyUnicode_Type, only invoking unicode_subtype_new for actual str subclasses. RustPython's PyStr::Constructor stripped the result via Self::from(s.as_wtf8().to_owned()) and re-materialized through into_ref_with_type, dropping the subclass type even when cls is exactly str. Add a slot_new branch that returns input.str(vm)? directly when cls is str_type with no encoding. Subtype construction and the bytes-decoding path are unchanged. Unmasks test_str.StrTest.test_conversion (11 assertTypedEqual cases).
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR adds a short-circuit optimization to Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Possibly related issues
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_str.py (TODO: 14) dependencies: dependent tests: (no tests depend on str) Legend:
|
ShaharNaveh
left a comment
There was a problem hiding this comment.
Great!
ty for finding these:)
thanks for the quick check ! |
Closes #7450.
Background
CPython's
unicode_new_impl(Objects/unicodeobject.c#L15575-L15596) only invokesunicode_subtype_newwhen the requested type is astrsubclass. Whentype == &PyUnicode_Type, it returns the result ofPyObject_Str(x)as-is, preserving anystrsubclass type that__str__or__repr__returned.RustPython's
PyStr::Constructor::py_newextracted the raw bytes viaSelf::from(s.as_wtf8().to_owned()), thenslot_newre-materialized throughinto_ref_with_type(vm, cls). This stripped the subclass type even whencls is str.Repro
Fix
Add a branch in
slot_newthat returnsinput.str(vm)?directly whencls is str_type(no subtype conversion, no encoding). Subtype construction (StrSubclass(...)) and thestr(bytes, encoding)decoding path are unchanged.Tests unmasked
test_str.StrTest.test_conversion(11assertTypedEqualcases coveringstr(WithStr/StrWithStr/WithRepr(...))×StrSubclass/OtherStrSubclasspermutations)Verification
str(),str('hi'),str(MyStr('x')),__str__/__repr__returning subclass,MyStr('z'),OtherStr(MyStr('w')),str(b'abc', 'utf-8'))test_str,test_descr,test_class,test_typing,test_userstring,test_format,test_pickle,test_io,test_collections,test_dict,test_set,test_exceptions,test_fstring,test_genericaliasSummary by CodeRabbit