Skip to content

ascii() discards str subclass type when repr result is already ASCII #7451

@jseop-lim

Description

@jseop-lim

Description

ascii() always creates a new plain str from the repr result, even when the repr is already ASCII. CPython's PyObject_ASCII returns the repr object directly when it's already ASCII, preserving str subclass types. This is a CPython compatibility issue.

Root Cause

builtin_ascii() unconditionally converts the repr result to a new AsciiString via to_ascii(), which then becomes a plain str through ToPyObject. The same pattern exists in PyObject::ascii().

CPython reference: object.c#L848-L849

// Key branch: return repr directly when it's already ASCII
if (PyUnicode_IS_ASCII(repr))
    return repr;

Fix

Add an ASCII check before to_ascii() — if the repr is already ASCII, return the repr object directly instead of creating a new string.

Reproduction

class MyStr(str):
    pass

class Foo:
    def __repr__(self):
        return MyStr('hello')

result = ascii(Foo())
print(type(result))

Output

RustPython:

<class 'str'>

CPython:

<class '__main__.MyStr'>

Environment

  • RustPython d248a04 (Python 3.14.0)
  • CPython 3.14.3
  • OS: Debian 12

Metadata

Metadata

Labels

C-compatA discrepancy between RustPython and CPython

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions