Skip to content

io.StringIO() checks initial_value before newline #9511

Closed

Description

@jseop-lim

Feature

When both arguments of io.StringIO(initial_value, newline) are invalid, RustPython raises the TypeError for initial_value, but CPython validates newline first and raises its ValueError.

Reproduction

import io

io.StringIO(True, "7")

RustPython:

TypeError: Expected type 'str' but 'bool' found.

CPython:

ValueError: illegal newline value: '7'

With only one invalid argument the exception class already matches, apart from the initial_value message, which CPython words as initial_value must be str or None, not bool.

Root cause

StringIONewArgs declares initial_value as Option<PyStrRef> ahead of newline, so FromArgs rejects a non-str initial value before Newlines::try_from_object runs. CPython's _io_StringIO___init___impl checks the type and value of newline and only then the type of initial_value.

Fix

Bind initial_value as Option<PyObjectRef> and downcast it to PyStr in StringIO::init, after newline has been converted.

Environment

  • RustPython 713e14c (0.6.1, Python 3.15.0a, macOS arm64), also reproduced on 0.4.0 (Debian 12)
  • CPython v3.15.2, also v3.14.4 and v3.12.10 (macOS arm64)

Python Documentation or reference to CPython source code

  • CPython _io_StringIO___init___impl: Modules/_io/stringio.c#L708-L721 rejects the newline value before it looks at initial_value:

    if (newline && newline[0] != '\0'
        && !(newline[0] == '\n' && newline[1] == '\0')
        && !(newline[0] == '\r' && newline[1] == '\0')
        && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
        PyErr_Format(PyExc_ValueError,
                     "illegal newline value: %R", newline_obj);
        return -1;
    }
    if (value && value != Py_None && !PyUnicode_Check(value)) {
        PyErr_Format(PyExc_TypeError,
                     "initial_value must be str or None, not %.200s",
                     Py_TYPE(value)->tp_name);
        return -1;
    }
  • Documentation: io.StringIO

AI disclosure: this report was drafted with Claude Code (claude-opus-5-5) and reviewed by me before submission. The divergence was found by differential testing against CPython and checked against CPython 3.15.2, and every source reference above was checked against the linked revisions.

Activity

  1. added
    C-compatA discrepancy between RustPython and CPython
    on Nov 1, 2026
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

    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