Rename parser mode from `Jupyter` to `Ipython` (#7153)

This commit is contained in:
Dhruv Manilawala 2023-09-05 19:42:26 +05:30 committed by GitHub
parent e02d76f070
commit 1adde24133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 35 additions and 41 deletions

View File

@ -20,7 +20,7 @@ pub(crate) struct Args {
pub(crate) fn main(args: &Args) -> Result<()> { pub(crate) fn main(args: &Args) -> Result<()> {
let contents = fs::read_to_string(&args.file)?; let contents = fs::read_to_string(&args.file)?;
let mode = if args.jupyter { let mode = if args.jupyter {
Mode::Jupyter Mode::Ipython
} else { } else {
Mode::Module Mode::Module
}; };

View File

@ -20,7 +20,7 @@ pub(crate) struct Args {
pub(crate) fn main(args: &Args) -> Result<()> { pub(crate) fn main(args: &Args) -> Result<()> {
let contents = fs::read_to_string(&args.file)?; let contents = fs::read_to_string(&args.file)?;
let mode = if args.jupyter { let mode = if args.jupyter {
Mode::Jupyter Mode::Ipython
} else { } else {
Mode::Module Mode::Module
}; };

View File

@ -1412,7 +1412,7 @@ mod tests {
let indentation = Indentation::default(); let indentation = Indentation::default();
let quote = Quote::default(); let quote = Quote::default();
let line_ending = LineEnding::default(); let line_ending = LineEnding::default();
let ast = ruff_python_parser::parse(contents, Mode::Jupyter, "<filename>").unwrap(); let ast = ruff_python_parser::parse(contents, Mode::Ipython, "<filename>").unwrap();
let Mod::Module(ModModule { body, .. }) = ast else { let Mod::Module(ModModule { body, .. }) = ast else {
panic!("Source code didn't return ModModule") panic!("Source code didn't return ModModule")
}; };

View File

@ -756,7 +756,7 @@ impl<'source> Lexer<'source> {
} }
c @ ('%' | '!') c @ ('%' | '!')
if self.mode == Mode::Jupyter if self.mode == Mode::Ipython
&& self.state.is_after_equal() && self.state.is_after_equal()
&& self.nesting == 0 => && self.nesting == 0 =>
{ {
@ -765,7 +765,7 @@ impl<'source> Lexer<'source> {
} }
c @ ('%' | '!' | '?' | '/' | ';' | ',') c @ ('%' | '!' | '?' | '/' | ';' | ',')
if self.mode == Mode::Jupyter && self.state.is_new_logical_line() => if self.mode == Mode::Ipython && self.state.is_new_logical_line() =>
{ {
let kind = if let Ok(kind) = IpyEscapeKind::try_from([c, self.cursor.first()]) { let kind = if let Ok(kind) = IpyEscapeKind::try_from([c, self.cursor.first()]) {
self.cursor.bump(); self.cursor.bump();
@ -778,7 +778,7 @@ impl<'source> Lexer<'source> {
self.lex_ipython_escape_command(kind) self.lex_ipython_escape_command(kind)
} }
'?' if self.mode == Mode::Jupyter => Tok::Question, '?' if self.mode == Mode::Ipython => Tok::Question,
'/' => { '/' => {
if self.cursor.eat_char('=') { if self.cursor.eat_char('=') {
@ -1220,7 +1220,7 @@ mod tests {
} }
pub(crate) fn lex_jupyter_source(source: &str) -> Vec<Tok> { pub(crate) fn lex_jupyter_source(source: &str) -> Vec<Tok> {
let lexer = lex(source, Mode::Jupyter); let lexer = lex(source, Mode::Ipython);
lexer.map(|x| x.unwrap().0).collect() lexer.map(|x| x.unwrap().0).collect()
} }

View File

@ -150,7 +150,7 @@ pub fn parse_program_tokens(
is_jupyter_notebook: bool, is_jupyter_notebook: bool,
) -> anyhow::Result<Suite, ParseError> { ) -> anyhow::Result<Suite, ParseError> {
let mode = if is_jupyter_notebook { let mode = if is_jupyter_notebook {
Mode::Jupyter Mode::Ipython
} else { } else {
Mode::Module Mode::Module
}; };
@ -267,15 +267,8 @@ pub enum Mode {
Module, Module,
/// The code consists of a single expression. /// The code consists of a single expression.
Expression, Expression,
/// The code consists of a sequence of statements which are part of a /// The code consists of a sequence of statements which can include the
/// Jupyter Notebook and thus could include escape commands scoped to /// escape commands that are part of IPython syntax.
/// a single line.
///
/// ## Limitations:
///
/// For [Dynamic object information], the escape characters (`?`, `??`)
/// must be used before an object. For example, `?foo` will be recognized,
/// but `foo?` will not.
/// ///
/// ## Supported escape commands: /// ## Supported escape commands:
/// ///
@ -290,7 +283,7 @@ pub enum Mode {
/// [Dynamic object information]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#dynamic-object-information /// [Dynamic object information]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#dynamic-object-information
/// [System shell access]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#system-shell-access /// [System shell access]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#system-shell-access
/// [Automatic parentheses and quotes]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#automatic-parentheses-and-quotes /// [Automatic parentheses and quotes]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#automatic-parentheses-and-quotes
Jupyter, Ipython,
} }
impl std::str::FromStr for Mode { impl std::str::FromStr for Mode {
@ -299,7 +292,7 @@ impl std::str::FromStr for Mode {
match s { match s {
"exec" | "single" => Ok(Mode::Module), "exec" | "single" => Ok(Mode::Module),
"eval" => Ok(Mode::Expression), "eval" => Ok(Mode::Expression),
"jupyter" => Ok(Mode::Jupyter), "ipython" => Ok(Mode::Ipython),
_ => Err(ModeParseError), _ => Err(ModeParseError),
} }
} }
@ -313,7 +306,7 @@ impl AsMode for PySourceType {
fn as_mode(&self) -> Mode { fn as_mode(&self) -> Mode {
match self { match self {
PySourceType::Python | PySourceType::Stub => Mode::Module, PySourceType::Python | PySourceType::Stub => Mode::Module,
PySourceType::Ipynb => Mode::Jupyter, PySourceType::Ipynb => Mode::Ipython,
} }
} }
} }
@ -324,7 +317,7 @@ pub struct ModeParseError;
impl std::fmt::Display for ModeParseError { impl std::fmt::Display for ModeParseError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, r#"mode must be "exec", "eval", "jupyter", or "single""#) write!(f, r#"mode must be "exec", "eval", "ipython", or "single""#)
} }
} }

View File

@ -156,7 +156,7 @@ pub fn parse_expression_starts_at(
/// ?str.replace /// ?str.replace
/// !ls /// !ls
/// "#; /// "#;
/// let program = parse(source, Mode::Jupyter, "<embedded>"); /// let program = parse(source, Mode::Ipython, "<embedded>");
/// assert!(program.is_ok()); /// assert!(program.is_ok());
/// ``` /// ```
pub fn parse(source: &str, mode: Mode, source_path: &str) -> Result<ast::Mod, ParseError> { pub fn parse(source: &str, mode: Mode, source_path: &str) -> Result<ast::Mod, ParseError> {
@ -1222,7 +1222,7 @@ foo.bar[0].baz[1]??
foo.bar[0].baz[2].egg?? foo.bar[0].baz[2].egg??
" "
.trim(), .trim(),
Mode::Jupyter, Mode::Ipython,
"<test>", "<test>",
) )
.unwrap(); .unwrap();
@ -1236,11 +1236,12 @@ a = 1
%timeit a == 1 %timeit a == 1
"# "#
.trim(); .trim();
let lxr = lexer::lex_starts_at(source, Mode::Jupyter, TextSize::default()); let lxr = lexer::lex_starts_at(source, Mode::Ipython, TextSize::default());
let parse_err = parse_tokens(lxr, Mode::Module, "<test>").unwrap_err(); let parse_err = parse_tokens(lxr, Mode::Module, "<test>").unwrap_err();
assert_eq!( assert_eq!(
parse_err.to_string(), parse_err.to_string(),
"IPython escape commands are only allowed in Jupyter mode at byte offset 6".to_string() "IPython escape commands are only allowed in `Mode::Ipython` at byte offset 6"
.to_string()
); );
} }
} }

View File

@ -325,7 +325,7 @@ AssertStatement: ast::Stmt = {
IpyEscapeCommandStatement: ast::Stmt = { IpyEscapeCommandStatement: ast::Stmt = {
<location:@L> <c:ipy_escape_command> <end_location:@R> =>? { <location:@L> <c:ipy_escape_command> <end_location:@R> =>? {
if mode == Mode::Jupyter { if mode == Mode::Ipython {
Ok(ast::Stmt::IpyEscapeCommand( Ok(ast::Stmt::IpyEscapeCommand(
ast::StmtIpyEscapeCommand { ast::StmtIpyEscapeCommand {
kind: c.0, kind: c.0,
@ -335,7 +335,7 @@ IpyEscapeCommandStatement: ast::Stmt = {
)) ))
} else { } else {
Err(LexicalError { Err(LexicalError {
error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), error: LexicalErrorType::OtherError("IPython escape commands are only allowed in `Mode::Ipython`".to_string()),
location, location,
})? })?
} }
@ -344,7 +344,7 @@ IpyEscapeCommandStatement: ast::Stmt = {
IpyEscapeCommandExpr: ast::ParenthesizedExpr = { IpyEscapeCommandExpr: ast::ParenthesizedExpr = {
<location:@L> <c:ipy_escape_command> <end_location:@R> =>? { <location:@L> <c:ipy_escape_command> <end_location:@R> =>? {
if mode == Mode::Jupyter { if mode == Mode::Ipython {
// This should never occur as the lexer won't allow it. // This should never occur as the lexer won't allow it.
if !matches!(c.0, IpyEscapeKind::Magic | IpyEscapeKind::Shell) { if !matches!(c.0, IpyEscapeKind::Magic | IpyEscapeKind::Shell) {
return Err(LexicalError { return Err(LexicalError {
@ -359,7 +359,7 @@ IpyEscapeCommandExpr: ast::ParenthesizedExpr = {
}.into()) }.into())
} else { } else {
Err(LexicalError { Err(LexicalError {
error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), error: LexicalErrorType::OtherError("IPython escape commands are only allowed in `Mode::Ipython`".to_string()),
location, location,
})? })?
} }
@ -403,10 +403,10 @@ IpyHelpEndEscapeCommandStatement: ast::Stmt = {
Ok(()) Ok(())
} }
if mode != Mode::Jupyter { if mode != Mode::Ipython {
return Err(ParseError::User { return Err(ParseError::User {
error: LexicalError { error: LexicalError {
error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), error: LexicalErrorType::OtherError("IPython escape commands are only allowed in `Mode::Ipython`".to_string()),
location, location,
}, },
}); });

View File

@ -1,5 +1,5 @@
// auto-generated: "lalrpop 0.20.0" // auto-generated: "lalrpop 0.20.0"
// sha3: 881894e86e83fb2796a9e4c17985d838c69f27db7808ddcdc24f35fd9aa742a2 // sha3: 516ee93137b3322a578922c24eb95daee3078883fdfa0c097268e64b78fcc54f
use num_bigint::BigInt; use num_bigint::BigInt;
use ruff_text_size::{Ranged, TextSize}; use ruff_text_size::{Ranged, TextSize};
use ruff_python_ast::{self as ast, IpyEscapeKind}; use ruff_python_ast::{self as ast, IpyEscapeKind};
@ -31681,7 +31681,7 @@ fn __action74<
) -> Result<ast::Stmt,__lalrpop_util::ParseError<TextSize,token::Tok,LexicalError>> ) -> Result<ast::Stmt,__lalrpop_util::ParseError<TextSize,token::Tok,LexicalError>>
{ {
{ {
if mode == Mode::Jupyter { if mode == Mode::Ipython {
Ok(ast::Stmt::IpyEscapeCommand( Ok(ast::Stmt::IpyEscapeCommand(
ast::StmtIpyEscapeCommand { ast::StmtIpyEscapeCommand {
kind: c.0, kind: c.0,
@ -31691,7 +31691,7 @@ fn __action74<
)) ))
} else { } else {
Err(LexicalError { Err(LexicalError {
error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), error: LexicalErrorType::OtherError("IPython escape commands are only allowed in `Mode::Ipython`".to_string()),
location, location,
})? })?
} }
@ -31709,7 +31709,7 @@ fn __action75<
) -> Result<ast::ParenthesizedExpr,__lalrpop_util::ParseError<TextSize,token::Tok,LexicalError>> ) -> Result<ast::ParenthesizedExpr,__lalrpop_util::ParseError<TextSize,token::Tok,LexicalError>>
{ {
{ {
if mode == Mode::Jupyter { if mode == Mode::Ipython {
// This should never occur as the lexer won't allow it. // This should never occur as the lexer won't allow it.
if !matches!(c.0, IpyEscapeKind::Magic | IpyEscapeKind::Shell) { if !matches!(c.0, IpyEscapeKind::Magic | IpyEscapeKind::Shell) {
return Err(LexicalError { return Err(LexicalError {
@ -31724,7 +31724,7 @@ fn __action75<
}.into()) }.into())
} else { } else {
Err(LexicalError { Err(LexicalError {
error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), error: LexicalErrorType::OtherError("IPython escape commands are only allowed in `Mode::Ipython`".to_string()),
location, location,
})? })?
} }
@ -31775,10 +31775,10 @@ fn __action76<
Ok(()) Ok(())
} }
if mode != Mode::Jupyter { if mode != Mode::Ipython {
return Err(ParseError::User { return Err(ParseError::User {
error: LexicalError { error: LexicalError {
error: LexicalErrorType::OtherError("IPython escape commands are only allowed in Jupyter mode".to_string()), error: LexicalErrorType::OtherError("IPython escape commands are only allowed in `Mode::Ipython`".to_string()),
location, location,
}, },
}); });

View File

@ -45,7 +45,7 @@ pub enum Tok {
triple_quoted: bool, triple_quoted: bool,
}, },
/// Token value for IPython escape commands. These are recognized by the lexer /// Token value for IPython escape commands. These are recognized by the lexer
/// only when the mode is [`Mode::Jupyter`]. /// only when the mode is [`Mode::Ipython`].
IpyEscapeCommand { IpyEscapeCommand {
/// The magic command value. /// The magic command value.
value: String, value: String,
@ -64,7 +64,7 @@ pub enum Tok {
/// Token value for a dedent. /// Token value for a dedent.
Dedent, Dedent,
EndOfFile, EndOfFile,
/// Token value for a question mark `?`. This is only used in [`Mode::Jupyter`]. /// Token value for a question mark `?`. This is only used in [`Mode::Ipython`].
Question, Question,
/// Token value for a left parenthesis `(`. /// Token value for a left parenthesis `(`.
Lpar, Lpar,
@ -211,7 +211,7 @@ pub enum Tok {
impl Tok { impl Tok {
pub fn start_marker(mode: Mode) -> Self { pub fn start_marker(mode: Mode) -> Self {
match mode { match mode {
Mode::Module | Mode::Jupyter => Tok::StartModule, Mode::Module | Mode::Ipython => Tok::StartModule,
Mode::Expression => Tok::StartExpression, Mode::Expression => Tok::StartExpression,
} }
} }