Skip to content

Commit 5448eac

Browse files
committed
fix input
1 parent 5b20c45 commit 5448eac

File tree

2 files changed

+11
-35
lines changed

2 files changed

+11
-35
lines changed

crates/vm/src/py_io.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,14 @@ pub fn file_readline(obj: &PyObject, size: Option<usize>, vm: &VirtualMachine) -
7070
};
7171
let ret = match_class!(match ret {
7272
s @ PyStr => {
73-
let s_val = s.as_str();
74-
if s_val.is_empty() {
73+
// Use as_wtf8() to handle strings with surrogates (e.g., surrogateescape)
74+
let s_wtf8 = s.as_wtf8();
75+
if s_wtf8.is_empty() {
7576
return Err(eof_err());
7677
}
77-
if let Some(no_nl) = s_val.strip_suffix('\n') {
78+
// '\n' is ASCII, so we can check bytes directly
79+
if s_wtf8.as_bytes().last() == Some(&b'\n') {
80+
let no_nl = &s_wtf8[..s_wtf8.len() - 1];
7881
vm.ctx.new_str(no_nl).into()
7982
} else {
8083
s.into()

crates/vm/src/stdlib/builtins.rs

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ pub use builtins::{ascii, print, reversed};
77

88
#[pymodule]
99
mod builtins {
10-
use std::io::IsTerminal;
11-
1210
use crate::{
1311
AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
1412
builtins::{
@@ -27,7 +25,6 @@ mod builtins {
2725
},
2826
protocol::{PyIter, PyIterReturn},
2927
py_io,
30-
readline::{Readline, ReadlineResult},
3128
stdlib::sys,
3229
types::PyComparisonOp,
3330
};
@@ -470,36 +467,12 @@ mod builtins {
470467

471468
let _ = vm.call_method(&stderr, "flush", ());
472469

473-
let fd_matches = |obj, expected| {
474-
vm.call_method(obj, "fileno", ())
475-
.and_then(|o| i64::try_from_object(vm, o))
476-
.is_ok_and(|fd| fd == expected)
477-
};
478-
479-
// everything is normal, we can just rely on rustyline to use stdin/stdout
480-
if fd_matches(&stdin, 0) && fd_matches(&stdout, 1) && std::io::stdin().is_terminal() {
481-
let prompt = prompt.as_ref().map_or("", |s| s.as_str());
482-
let mut readline = Readline::new(());
483-
match readline.readline(prompt) {
484-
ReadlineResult::Line(s) => Ok(vm.ctx.new_str(s).into()),
485-
ReadlineResult::Eof => {
486-
Err(vm.new_exception_empty(vm.ctx.exceptions.eof_error.to_owned()))
487-
}
488-
ReadlineResult::Interrupt => {
489-
Err(vm.new_exception_empty(vm.ctx.exceptions.keyboard_interrupt.to_owned()))
490-
}
491-
ReadlineResult::Io(e) => Err(vm.new_os_error(e.to_string())),
492-
#[cfg(unix)]
493-
ReadlineResult::OsError(num) => Err(vm.new_os_error(num.to_string())),
494-
ReadlineResult::Other(e) => Err(vm.new_runtime_error(e.to_string())),
495-
}
496-
} else {
497-
if let OptionalArg::Present(prompt) = prompt {
498-
vm.call_method(&stdout, "write", (prompt,))?;
499-
}
500-
let _ = vm.call_method(&stdout, "flush", ());
501-
py_io::file_readline(&stdin, None, vm)
470+
// Use simple stdin readline (like fgets).
471+
if let OptionalArg::Present(prompt) = prompt {
472+
vm.call_method(&stdout, "write", (prompt,))?;
502473
}
474+
let _ = vm.call_method(&stdout, "flush", ());
475+
py_io::file_readline(&stdin, None, vm)
503476
}
504477

505478
#[pyfunction]

0 commit comments

Comments
 (0)