← index #18941Issue #18942
Related · high · value 3.035
QUERY · ISSUE

`repr()` does not raise TypeError when `__repr__` returns a non-string

openby jseop-limopened 2026-03-17updated 2026-03-20
bug

Port, board and/or hardware

Unix port, Linux

MicroPython version

v1.27.0

Reproduction

class Foo:
    def __repr__(self):
        return True

print(repr(Foo()))

Expected behaviour

CPython v3.11.15:

TypeError: __repr__ returned non-string (type bool)

Observed behaviour

MicroPython v1.27.0:

True

Additional Information

repr() does not raise TypeError when a user-defined __repr__ method returns a non-string value. Instead, MicroPython silently converts and returns the value as a string. This is a CPython compatibility issue.

Root Cause

instance_print in objtype.c calls the user-defined __repr__ method via mp_call_function_1 and passes the result directly to mp_obj_print_helper without validating that the return value is a string.

CPython reference: Objects/object.c#L439-L445

// CPython validates that __repr__ returns a string, raises TypeError otherwise
if (!PyUnicode_Check(res)) {
    _PyErr_Format(tstate, PyExc_TypeError,
                  "__repr__ returned non-string (type %.200s)",
                  Py_TYPE(res)->tp_name);
    Py_DECREF(res);
    return NULL;
}

Fix

Add a mp_obj_is_str(r) check after calling the __repr__ method in instance_print, and raise TypeError if the return value is not a string.

Code of Conduct

Yes, I agree

CANDIDATE · ISSUE

`repr()` does not preserve `str` subclass type returned by `__repr__`

openby jseop-limopened 2026-03-17updated 2026-03-20
bug

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:

<class '__main__.MyStr'>

Observed behaviour

MicroPython v1.27.0:

<class 'str'>

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

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied