Skip to content

should we change str/unicode implementation for PEP 383 ? #935

Closed

Description

@jgirardet

when decoding/encoding some str/bytes you can (for example) :
'strict' : raise an exception
'ignore' : wrong bytes are kicked out
'replace' : wrong bytes are replaced by the UNICODE_REPLACEMENT_CHAR
'backslashreplace' : Replace with backslashed escape sequences

No problem with current implementation for these ones.

This PEP proposes a means of dealing with [such] irregularities by embedding the bytes in character strings in such a way that allows recreation of the original byte string.

'surrogateescape' : replace wrong bytes by surrogate

With this PEP, non-decodable bytes >= 128 will be represented as lone surrogate codes U+DC80..U+DCFF.

But the actual RustPython implementation stores str as valid unicode then :

a.push('\u{dcc3}');
help: src/main.rs:25: unicode escape must not be a surrogate

storing surrogate is not allowed.
I tried to do it inside an unsafe block it's not possible either.

I'm note sure to have a clear idea howto to do it. I was thinking to a wrapper on a "homemade" unicode and the Rust unicode implementation to store strings, but actually python is able to call some methods on invalid utf8 sequence :

a.capitalize()                                                         
>>>  '\udcc3\udca9'

I'd be happy to have some opinion about it.

Activity

  1. OddBloke commented on Oct 28, 2021

    @OddBloke
    Collaborator

    I'm not 100% sure if what I'm seeing is related but I'm seeing inconsistencies in how RustPython handles surrogates vs CPython. This is CPython:

    >>> "A\udcdeB".encode('utf-8')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'utf-8' codec can't encode character '\udcde' in position 1: surrogates not allowed

    and this is RustPython:

    >>>>> "A\udcdeB".encode('utf-8')
    b'A\xef\xbf\xbdB'

    (This is causing a test to unexpectedly pass, because CPython rejects that string as the first argument to type() but we do not.)

  2. youknowone commented on Oct 31, 2021

    @youknowone
    Member

    Probably we need another str kind presented by &[u32]

  3. youknowone commented on Dec 25, 2025

    @youknowone
    Member

    we now have wtf8-backed str.

    >>>>> "A\udcdeB".encode('utf-8')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: ('utf-8', 'A\udcdeB', 1, 2, 'surrogates not allowed')
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-designAbout RustPython's own implementationA-stdlib

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions