Port, board and/or hardware
Unix port, Linux
MicroPython version
MicroPython v1.27.0 on 2026-03-12
Reproduction
class MyStr(str):
pass
class Foo:
def __repr__(self):
return MyStr("hello")
result = repr(Foo())
print(type(result))
Expected behaviour
CPython 3.11.15:
Observed behaviour
MicroPython v1.27.0:
Additional Information
When __repr__ returns an instance of a str subclass, repr() discards the subclass type and returns a plain str. CPython preserves the original subclass type. This is a CPython compatibility issue.
Root Cause
mp_builtin_repr() serializes the __repr__ result into a text buffer (vstr) via mp_obj_print_helper(), then constructs a new plain str from that buffer using mp_obj_new_str_from_utf8_vstr(), which hardcodes &mp_type_str as the type. This discards the original str subclass type.
CPython reference: object.c#L402-L451
// CPython returns the __repr__ result directly, preserving str subclass type
res = (*Py_TYPE(v)->tp_repr)(v);
if (!PyUnicode_Check(res)) { // PyUnicode_Check accepts str subclasses
// raise TypeError...
}
return res; // original object returned as-is
Fix
Document this as a known difference in tests/cpydiff/ (similar to the existing int subclass entry "No int conversion for int-derived types available"), or change mp_builtin_repr() to return the __repr__ result object directly when it is a str (or subclass) instead of serializing through a buffer.
Code of Conduct
Yes, I agree
Port, board and/or hardware
Unix port, Linux
MicroPython version
MicroPython v1.27.0 on 2026-03-12
Reproduction
Expected behaviour
CPython 3.11.15:
Observed behaviour
MicroPython v1.27.0:
Additional Information
When
__repr__returns an instance of astrsubclass,repr()discards the subclass type and returns a plainstr. CPython preserves the original subclass type. This is a CPython compatibility issue.Root Cause
mp_builtin_repr()serializes the__repr__result into a text buffer (vstr) viamp_obj_print_helper(), then constructs a new plainstrfrom that buffer usingmp_obj_new_str_from_utf8_vstr(), which hardcodes&mp_type_stras the type. This discards the originalstrsubclass type.Fix
Document this as a known difference in
tests/cpydiff/(similar to the existingintsubclass entry "No int conversion for int-derived types available"), or changemp_builtin_repr()to return the__repr__result object directly when it is astr(or subclass) instead of serializing through a buffer.Code of Conduct
Yes, I agree