Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions crates/vm/src/stdlib/_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4864,7 +4864,7 @@ mod _io {
struct StringIONewArgs {
// None means an empty buffer.
#[pyarg(any, optional, py_default = "''")]
initial_value: Option<PyStrRef>,
initial_value: Option<PyObjectRef>,

// Omitted newline is \n. None selects universal newlines.
#[pyarg(any, default, py_default = "'\\n'")]
Expand Down Expand Up @@ -4894,13 +4894,24 @@ mod _io {
initial_value,
newline,
}: Self::Args,
_vm: &VirtualMachine,
vm: &VirtualMachine,
) -> PyResult<()> {
let newline = match newline {
OptionalArg::Missing => Newlines::Lf,
OptionalArg::Present(None) => Newlines::Universal,
OptionalArg::Present(Some(newline)) => newline,
};
// Checked here rather than while binding, so a bad newline is reported first.
let initial_value = initial_value
.map(|value| {
value.downcast::<PyStr>().map_err(|value| {
vm.new_type_error(format!(
"initial_value must be str or None, not {}",
value.class().slot_name()
))
})
})
.transpose()?;
let raw_bytes = initial_value.as_ref().map_or_else(Vec::new, |v| {
Self::translate_newlines(v.as_wtf8(), newline).into_bytes()
});
Expand Down
14 changes: 14 additions & 0 deletions extra_tests/snippets/stdlib_io_stringio.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from io import StringIO

from testutils import assert_raises


def test_01():
"""
Expand Down Expand Up @@ -84,10 +86,22 @@ def test_06():
assert False


def test_07():
"""
Test that newline is validated before initial_value
"""
assert_raises(ValueError, StringIO, True, "7")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Limit existing test-file edits to the permitted failure markers

This adds assertions and executable test logic to an existing test file, but the root AGENTS.md explicitly limits test-file modifications to adding/removing @unittest.expectedFailure decorators and removing associated TODO comments. The new test_07, helper import, and invocation therefore violate the repository’s critical test-modification restriction; retain the Rust implementation fix without these snippet additions.

AGENTS.md reference: AGENTS.md:L280-L282

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That section covers the CPython tests in Lib/test. For extra_tests/snippets, AGENTS.md asks for new tests in the most closely related existing file (L119-L120), which is what this does.

with assert_raises(TypeError) as cm:
StringIO(True)
assert str(cm.exception) == "initial_value must be str or None, not bool"
assert StringIO(None, "\r").getvalue() == ""


if __name__ == "__main__":
test_01()
test_02()
test_03()
test_04()
test_05()
test_06()
test_07()
Loading