🌐 AI搜索 & 代理 主页
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
continue accepting REPL input for multiline strings
  • Loading branch information
aneeshdurg committed May 23, 2025
commit 65ca012d46beac45d9612b8bccd1d02f3e4fc82e
2 changes: 2 additions & 0 deletions compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum CompileErrorType {
pub struct ParseError {
#[source]
pub error: parser::ParseErrorType,
pub raw_location: ruff_text_size::TextRange,
pub location: SourceLocation,
pub source_path: String,
}
Expand All @@ -48,6 +49,7 @@ impl CompileError {
let location = source_code.source_location(error.location.start());
Self::Parse(ParseError {
error: error.error,
raw_location: error.location,
location,
source_path: source_code.path.to_owned(),
})
Expand Down
35 changes: 34 additions & 1 deletion src/shell.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
mod helper;

use rustpython_compiler::{
CompileError, ParseError, parser::LexicalErrorType, parser::ParseErrorType,
CompileError, ParseError, parser::FStringErrorType, parser::LexicalErrorType,
parser::ParseErrorType,
};
use rustpython_vm::{
AsObject, PyResult, VirtualMachine,
Expand All @@ -24,6 +25,12 @@ fn shell_exec(
empty_line_given: bool,
continuing: bool,
) -> ShellExecResult {
// compiling expects only UNIX style line endings, and will replace windows line endings
// internally. Since we might need to analyze the source to determine if an error could be
// resolved by future input, we need the location from the error to match the source code that
// was actually compiled.
#[cfg(windows)]
let source = &source.replace("\r\n", "\n");
match vm.compile(source, compiler::Mode::Single, "<stdin>".to_owned()) {
Ok(code) => {
if empty_line_given || !continuing {
Expand All @@ -41,7 +48,33 @@ fn shell_exec(
error: ParseErrorType::Lexical(LexicalErrorType::Eof),
..
})) => ShellExecResult::Continue,
Err(CompileError::Parse(ParseError {
error:
ParseErrorType::Lexical(LexicalErrorType::FStringError(
FStringErrorType::UnterminatedTripleQuotedString,
)),
..
})) => ShellExecResult::Continue,
Err(err) => {
// Check if the error is from an unclosed triple quoted string (which should always
// continue)
match err {
CompileError::Parse(ParseError {
error: ParseErrorType::Lexical(LexicalErrorType::UnclosedStringError),
raw_location,
..
}) => {
let loc = raw_location.start().to_usize();
let mut iter = source.chars();
if let Some(quote) = iter.nth(loc) {
if iter.next() == Some(quote) && iter.next() == Some(quote) {
return ShellExecResult::Continue;
}
}
}
_ => (),
};

// bad_error == true if we are handling an error that should be thrown even if we are continuing
// if its an indentation error, set to true if we are continuing and the error is on column 0,
// since indentations errors on columns other than 0 should be ignored.
Expand Down
1 change: 1 addition & 0 deletions vm/src/stdlib/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ pub(crate) fn parse(
let top = parser::parse(source, mode.into())
.map_err(|parse_error| ParseError {
error: parse_error.error,
raw_location: parse_error.location,
location: text_range_to_source_range(&source_code, parse_error.location)
.start
.to_source_location(),
Expand Down