diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fa5f8a8f..68d70799 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -59,7 +59,7 @@ jobs: - name: install ruff run: python -m pip install ruff - name: run python lint - run: ruff --ignore=E501 ast --show-source + run: ruff --ignore=E501 ruff_python_ast --show-source - name: spell checker uses: streetsidesoftware/cspell-action@v2 diff --git a/Cargo.toml b/Cargo.toml index 7949185b..e2ad76a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace.package] version = "0.2.0" -authors = ["RustPython Team"] +authors = ["RustPython Team", "Charlie Marsh "] edition = "2021" rust-version = "1.67.1" description = "Python parser and its dependencies." @@ -11,17 +11,16 @@ include = ["LICENSE", "Cargo.toml", "src/**/*.rs"] [workspace] resolver = "2" members = [ - "ast", "core", "format", "literal", "parser", "ruff_text_size", + "ruff_python_ast", "literal", "ruff_python_parser", "ruff_text_size", ] [workspace.dependencies] -rustpython-ast = { path = "ast", default-features = false } -rustpython-parser-core = { path = "core", features = [] } +ruff_python_ast = { path = "ruff_python_ast" } rustpython-literal = { path = "literal" } -rustpython-format = { path = "format" } -rustpython-parser = { path = "parser", default-features = false } +ruff_text_size = { path = "ruff_text_size" } anyhow = "1.0.45" +bitflags = "2.3.3" cfg-if = "1.0" insta = "1.14.0" itertools = "0.10.3" diff --git a/ast/Cargo.toml b/ast/Cargo.toml deleted file mode 100644 index 03a566e0..00000000 --- a/ast/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "rustpython-ast" -version = "0.2.0" -description = "AST definitions for RustPython" -authors = ["RustPython Team"] -edition = "2021" -repository = "https://github.com/RustPython/Parser/" -license = "MIT" - -[dependencies] -rustpython-parser-core = { workspace = true } -rustpython-literal = { workspace = true, optional = true } - -is-macro = { workspace = true } -num-bigint = { workspace = true } -static_assertions = "1.1.0" diff --git a/ast/src/builtin.rs b/ast/src/builtin.rs deleted file mode 100644 index e10b8245..00000000 --- a/ast/src/builtin.rs +++ /dev/null @@ -1,203 +0,0 @@ -//! `builtin_types` in Attributed - -use rustpython_parser_core::text_size::TextRange; - -use crate::Ranged; -use num_bigint::BigInt; - -pub type String = std::string::String; - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Identifier { - id: String, - range: TextRange, -} - -impl Identifier { - #[inline] - pub fn new(id: impl Into, range: TextRange) -> Self { - Self { - id: id.into(), - range, - } - } -} - -impl Identifier { - #[inline] - pub fn as_str(&self) -> &str { - self.id.as_str() - } -} - -impl PartialEq for Identifier { - #[inline] - fn eq(&self, other: &str) -> bool { - self.id == other - } -} - -impl PartialEq for Identifier { - #[inline] - fn eq(&self, other: &String) -> bool { - &self.id == other - } -} - -impl std::ops::Deref for Identifier { - type Target = str; - #[inline] - fn deref(&self) -> &Self::Target { - self.id.as_str() - } -} - -impl AsRef for Identifier { - #[inline] - fn as_ref(&self) -> &str { - self.id.as_str() - } -} - -impl AsRef for Identifier { - #[inline] - fn as_ref(&self) -> &String { - &self.id - } -} - -impl std::fmt::Display for Identifier { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.id.fmt(f) - } -} - -impl From for String { - #[inline] - fn from(identifier: Identifier) -> String { - identifier.id - } -} - -impl Ranged for Identifier { - fn range(&self) -> TextRange { - self.range - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Int(u32); - -impl Int { - pub fn new(i: u32) -> Self { - Self(i) - } - pub fn to_u32(&self) -> u32 { - self.0 - } - pub fn to_usize(&self) -> usize { - self.0 as _ - } -} - -impl std::cmp::PartialEq for Int { - #[inline] - fn eq(&self, other: &u32) -> bool { - self.0 == *other - } -} - -impl std::cmp::PartialEq for Int { - #[inline] - fn eq(&self, other: &usize) -> bool { - self.0 as usize == *other - } -} - -#[derive(Clone, Debug, PartialEq, is_macro::Is)] -pub enum Constant { - None, - Bool(bool), - Str(String), - Bytes(Vec), - Int(BigInt), - Float(f64), - Complex { real: f64, imag: f64 }, - Ellipsis, -} - -impl Constant { - pub fn is_true(self) -> bool { - self.bool().map_or(false, |b| b) - } - pub fn is_false(self) -> bool { - self.bool().map_or(false, |b| !b) - } - pub fn complex(self) -> Option<(f64, f64)> { - match self { - Constant::Complex { real, imag } => Some((real, imag)), - _ => None, - } - } -} - -impl From for Constant { - fn from(s: String) -> Constant { - Self::Str(s) - } -} -impl From> for Constant { - fn from(b: Vec) -> Constant { - Self::Bytes(b) - } -} -impl From for Constant { - fn from(b: bool) -> Constant { - Self::Bool(b) - } -} -impl From for Constant { - fn from(i: BigInt) -> Constant { - Self::Int(i) - } -} - -#[cfg(feature = "rustpython-literal")] -impl std::fmt::Display for Constant { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Constant::None => f.pad("None"), - Constant::Bool(b) => f.pad(if *b { "True" } else { "False" }), - Constant::Str(s) => rustpython_literal::escape::UnicodeEscape::new_repr(s.as_str()) - .str_repr() - .write(f), - Constant::Bytes(b) => { - let escape = rustpython_literal::escape::AsciiEscape::new_repr(b); - let repr = escape.bytes_repr().to_string().unwrap(); - f.pad(&repr) - } - Constant::Int(i) => i.fmt(f), - Constant::Float(fp) => f.pad(&rustpython_literal::float::to_string(*fp)), - Constant::Complex { real, imag } => { - if *real == 0.0 { - write!(f, "{imag}j") - } else { - write!(f, "({real}{imag:+}j)") - } - } - Constant::Ellipsis => f.pad("..."), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_is_macro() { - let none = Constant::None; - assert!(none.is_none()); - assert!(!none.is_bool()); - } -} diff --git a/ast/src/impls.rs b/ast/src/impls.rs deleted file mode 100644 index 9c564ad8..00000000 --- a/ast/src/impls.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::{Constant, Expr}; - -impl Expr { - /// Returns a short name for the node suitable for use in error messages. - pub fn python_name(&self) -> &'static str { - match self { - Expr::BoolOp { .. } | Expr::BinOp { .. } | Expr::UnaryOp { .. } => "operator", - Expr::Subscript { .. } => "subscript", - Expr::Await { .. } => "await expression", - Expr::Yield { .. } | Expr::YieldFrom { .. } => "yield expression", - Expr::Compare { .. } => "comparison", - Expr::Attribute { .. } => "attribute", - Expr::Call { .. } => "function call", - Expr::Constant(crate::ExprConstant { value, .. }) => match value { - Constant::Str(_) - | Constant::Int(_) - | Constant::Float(_) - | Constant::Complex { .. } - | Constant::Bytes(_) => "literal", - Constant::Bool(b) => { - if *b { - "True" - } else { - "False" - } - } - Constant::None => "None", - Constant::Ellipsis => "ellipsis", - }, - Expr::List { .. } => "list", - Expr::Tuple { .. } => "tuple", - Expr::Dict { .. } => "dict display", - Expr::Set { .. } => "set display", - Expr::ListComp { .. } => "list comprehension", - Expr::DictComp { .. } => "dict comprehension", - Expr::SetComp { .. } => "set comprehension", - Expr::GeneratorExp { .. } => "generator expression", - Expr::Starred { .. } => "starred", - Expr::Slice { .. } => "slice", - Expr::JoinedStr(crate::ExprJoinedStr { values, .. }) => { - if values.iter().any(|e| e.is_joined_str_expr()) { - "f-string expression" - } else { - "literal" - } - } - Expr::FormattedValue { .. } => "f-string expression", - Expr::Name { .. } => "name", - Expr::Lambda { .. } => "lambda", - Expr::IfExp { .. } => "conditional expression", - Expr::NamedExpr { .. } => "named expression", - Expr::LineMagic(_) => "line magic", - } - } -} - -#[cfg(target_arch = "x86_64")] -static_assertions::assert_eq_size!(crate::Expr, [u8; 72]); -#[cfg(target_arch = "x86_64")] -static_assertions::assert_eq_size!(crate::Stmt, [u8; 168]); -#[cfg(target_arch = "x86_64")] -static_assertions::assert_eq_size!(crate::Pattern, [u8; 96]); -#[cfg(target_arch = "x86_64")] -static_assertions::assert_eq_size!(crate::ExceptHandler, [u8; 72]); diff --git a/ast/src/ranged.rs b/ast/src/ranged.rs deleted file mode 100644 index 1893fd1c..00000000 --- a/ast/src/ranged.rs +++ /dev/null @@ -1,577 +0,0 @@ -// This file was originally generated from asdl by a python script, but we now edit it manually - -use crate::text_size::{TextRange, TextSize}; - -pub trait Ranged { - fn range(&self) -> TextRange; - - fn start(&self) -> TextSize { - self.range().start() - } - - fn end(&self) -> TextSize { - self.range().end() - } -} - -impl Ranged for TextRange { - fn range(&self) -> TextRange { - *self - } -} - -impl Ranged for &T -where - T: Ranged, -{ - fn range(&self) -> TextRange { - T::range(self) - } -} - -impl Ranged for crate::generic::ModModule { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ModInteractive { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ModExpression { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ModFunctionType { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::Mod { - fn range(&self) -> TextRange { - match self { - Self::Module(node) => node.range(), - Self::Interactive(node) => node.range(), - Self::Expression(node) => node.range(), - Self::FunctionType(node) => node.range(), - } - } -} - -impl Ranged for crate::generic::StmtFunctionDef { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtAsyncFunctionDef { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtClassDef { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtReturn { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtDelete { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtTypeAlias { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtAssign { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtAugAssign { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtAnnAssign { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtFor { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtAsyncFor { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtWhile { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtIf { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ElifElseClause { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtWith { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtAsyncWith { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtMatch { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtRaise { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtTry { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtTryStar { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtAssert { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtImport { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtImportFrom { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtGlobal { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtNonlocal { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtExpr { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtPass { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtBreak { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtContinue { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::StmtLineMagic { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::Stmt { - fn range(&self) -> TextRange { - match self { - Self::FunctionDef(node) => node.range(), - Self::AsyncFunctionDef(node) => node.range(), - Self::ClassDef(node) => node.range(), - Self::Return(node) => node.range(), - Self::Delete(node) => node.range(), - Self::TypeAlias(node) => node.range(), - Self::Assign(node) => node.range(), - Self::AugAssign(node) => node.range(), - Self::AnnAssign(node) => node.range(), - Self::For(node) => node.range(), - Self::AsyncFor(node) => node.range(), - Self::While(node) => node.range(), - Self::If(node) => node.range(), - Self::With(node) => node.range(), - Self::AsyncWith(node) => node.range(), - Self::Match(node) => node.range(), - Self::Raise(node) => node.range(), - Self::Try(node) => node.range(), - Self::TryStar(node) => node.range(), - Self::Assert(node) => node.range(), - Self::Import(node) => node.range(), - Self::ImportFrom(node) => node.range(), - Self::Global(node) => node.range(), - Self::Nonlocal(node) => node.range(), - Self::Expr(node) => node.range(), - Self::Pass(node) => node.range(), - Self::Break(node) => node.range(), - Self::Continue(node) => node.range(), - Self::LineMagic(node) => node.range(), - } - } -} - -impl Ranged for crate::generic::ExprBoolOp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprNamedExpr { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprBinOp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprUnaryOp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprLambda { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprIfExp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprDict { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprSet { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprListComp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprSetComp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprDictComp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprGeneratorExp { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprAwait { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprYield { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprYieldFrom { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprCompare { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprCall { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprFormattedValue { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprJoinedStr { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprConstant { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprAttribute { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprSubscript { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprStarred { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprName { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprList { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprTuple { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprSlice { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExprLineMagic { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::Expr { - fn range(&self) -> TextRange { - match self { - Self::BoolOp(node) => node.range(), - Self::NamedExpr(node) => node.range(), - Self::BinOp(node) => node.range(), - Self::UnaryOp(node) => node.range(), - Self::Lambda(node) => node.range(), - Self::IfExp(node) => node.range(), - Self::Dict(node) => node.range(), - Self::Set(node) => node.range(), - Self::ListComp(node) => node.range(), - Self::SetComp(node) => node.range(), - Self::DictComp(node) => node.range(), - Self::GeneratorExp(node) => node.range(), - Self::Await(node) => node.range(), - Self::Yield(node) => node.range(), - Self::YieldFrom(node) => node.range(), - Self::Compare(node) => node.range(), - Self::Call(node) => node.range(), - Self::FormattedValue(node) => node.range(), - Self::JoinedStr(node) => node.range(), - Self::Constant(node) => node.range(), - Self::Attribute(node) => node.range(), - Self::Subscript(node) => node.range(), - Self::Starred(node) => node.range(), - Self::Name(node) => node.range(), - Self::List(node) => node.range(), - Self::Tuple(node) => node.range(), - Self::Slice(node) => node.range(), - Self::LineMagic(node) => node.range(), - } - } -} - -impl Ranged for crate::generic::Comprehension { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ExceptHandlerExceptHandler { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::ExceptHandler { - fn range(&self) -> TextRange { - match self { - Self::ExceptHandler(node) => node.range(), - } - } -} - -impl Ranged for crate::generic::PythonArguments { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::Arg { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::Keyword { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::Alias { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::WithItem { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::MatchCase { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchValue { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchSingleton { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchSequence { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchMapping { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchClass { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchStar { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchAs { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::PatternMatchOr { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::Pattern { - fn range(&self) -> TextRange { - match self { - Self::MatchValue(node) => node.range(), - Self::MatchSingleton(node) => node.range(), - Self::MatchSequence(node) => node.range(), - Self::MatchMapping(node) => node.range(), - Self::MatchClass(node) => node.range(), - Self::MatchStar(node) => node.range(), - Self::MatchAs(node) => node.range(), - Self::MatchOr(node) => node.range(), - } - } -} - -impl Ranged for crate::generic::TypeIgnoreTypeIgnore { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::TypeIgnore { - fn range(&self) -> TextRange { - match self { - Self::TypeIgnore(node) => node.range(), - } - } -} -impl Ranged for crate::generic::TypeParamTypeVar { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::TypeParamTypeVarTuple { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::TypeParamParamSpec { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::TypeParam { - fn range(&self) -> TextRange { - match self { - Self::TypeVar(node) => node.range(), - Self::TypeVarTuple(node) => node.range(), - Self::ParamSpec(node) => node.range(), - } - } -} -impl Ranged for crate::generic::Decorator { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::Arguments { - fn range(&self) -> TextRange { - self.range - } -} -impl Ranged for crate::generic::ArgWithDefault { - fn range(&self) -> TextRange { - self.range - } -} diff --git a/core/Cargo.toml b/core/Cargo.toml deleted file mode 100644 index 2c477757..00000000 --- a/core/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "rustpython-parser-core" -description = "RustPython parser data types." -version = "0.2.0" -authors = ["RustPython Team"] -edition = "2021" -repository = "https://github.com/RustPython/Parser/" -license = "MIT" - -[dependencies] -# ruff dependency shouldn't be placed out of this crate -ruff_text_size = { path = "../ruff_text_size" } - -serde = { version = "1.0.133", optional = true, default-features = false, features = ["derive"] } -is-macro.workspace = true - -[features] -default = [] diff --git a/core/src/error.rs b/core/src/error.rs deleted file mode 100644 index 4b9b197c..00000000 --- a/core/src/error.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::text_size::TextSize; -use std::fmt::Display; - -#[derive(Debug, PartialEq, Eq)] -pub struct BaseError { - pub error: T, - pub offset: TextSize, - pub source_path: String, -} - -impl std::ops::Deref for BaseError { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.error - } -} - -impl std::error::Error for BaseError -where - T: std::error::Error + 'static, -{ - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - Some(&self.error) - } -} - -impl Display for BaseError -where - T: std::fmt::Display, -{ - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "{} at byte offset {}", - &self.error, - u32::from(self.offset) - ) - } -} - -impl BaseError { - pub fn error(self) -> T { - self.error - } - - pub fn from(obj: BaseError) -> Self - where - U: Into, - { - Self { - error: obj.error.into(), - offset: obj.offset, - source_path: obj.source_path, - } - } - - pub fn into(self) -> BaseError - where - T: Into, - { - BaseError::from(self) - } -} diff --git a/core/src/format.rs b/core/src/format.rs deleted file mode 100644 index d0820299..00000000 --- a/core/src/format.rs +++ /dev/null @@ -1,25 +0,0 @@ -/// Transforms a value prior to formatting it. -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, is_macro::Is)] -#[repr(i8)] -pub enum ConversionFlag { - /// No conversion - None = -1, // CPython uses -1 - /// Converts by calling `str()`. - Str = b's' as i8, - /// Converts by calling `ascii()`. - Ascii = b'a' as i8, - /// Converts by calling `repr()`. - Repr = b'r' as i8, -} - -impl ConversionFlag { - pub fn to_byte(&self) -> Option { - match self { - Self::None => None, - flag => Some(*flag as u8), - } - } - pub fn to_char(&self) -> Option { - Some(self.to_byte()? as char) - } -} diff --git a/core/src/lib.rs b/core/src/lib.rs deleted file mode 100644 index 47dc115c..00000000 --- a/core/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/main/logo.png")] -#![doc(html_root_url = "https://docs.rs/rustpython-parser-core/")] - -mod error; -mod format; -pub mod mode; - -pub use error::BaseError; -pub use format::ConversionFlag; -pub use mode::Mode; - -// re-export our public interface -pub use ruff_text_size as text_size; diff --git a/core/src/mode.rs b/core/src/mode.rs deleted file mode 100644 index d84b76ce..00000000 --- a/core/src/mode.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! Control in the different modes by which a source file can be parsed. - -/// The mode argument specifies in what way code must be parsed. -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Mode { - /// The code consists of a sequence of statements. - Module, - /// The code consists of a sequence of interactive statement. - Interactive, - /// The code consists of a single expression. - Expression, - /// The code consists of a sequence of statements which are part of a - /// Jupyter Notebook and thus could include escape commands scoped to - /// 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: - /// - /// - [Magic command system] which is limited to [line magics] and can start - /// with `?` or `??`. - /// - [Dynamic object information] which can start with `?` or `??`. - /// - [System shell access] which can start with `!` or `!!`. - /// - [Automatic parentheses and quotes] which can start with `/`, `;`, or `,`. - /// - /// [Magic command system]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#magic-command-system - /// [line magics]: https://ipython.readthedocs.io/en/stable/interactive/magics.html#line-magics - /// [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 - /// [Automatic parentheses and quotes]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#automatic-parentheses-and-quotes - Jupyter, -} - -impl std::str::FromStr for Mode { - type Err = ModeParseError; - fn from_str(s: &str) -> Result { - match s { - "exec" | "single" => Ok(Mode::Module), - "eval" => Ok(Mode::Expression), - "jupyter" => Ok(Mode::Jupyter), - _ => Err(ModeParseError), - } - } -} - -/// Returned when a given mode is not valid. -#[derive(Debug)] -pub struct ModeParseError; - -impl std::fmt::Display for ModeParseError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, r#"mode must be "exec", "eval", "jupyter", or "single""#) - } -} diff --git a/format/Cargo.toml b/format/Cargo.toml deleted file mode 100644 index 0fda5abc..00000000 --- a/format/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "rustpython-format" -edition = "2021" -version = "0.2.0" -description = "Format helpers for RustPython" -authors = ["RustPython Team"] -repository = "https://github.com/RustPython/Parser/" -license = "MIT" - -[dependencies] -rustpython-literal = { workspace = true } - -bitflags = "2.3.1" -itertools = "0.10.5" -num-traits = { workspace = true } -num-bigint = { workspace = true } - -[features] diff --git a/format/src/format.rs b/format/src/format.rs deleted file mode 100644 index 09e42b80..00000000 --- a/format/src/format.rs +++ /dev/null @@ -1,1272 +0,0 @@ -use itertools::{Itertools, PeekingNext}; - -use num_traits::{cast::ToPrimitive, FromPrimitive, Signed}; -use rustpython_literal::float; -use rustpython_literal::format::Case; -use std::ops::Deref; -use std::{cmp, str::FromStr}; - -use num_bigint::{BigInt, Sign}; - -trait FormatParse { - fn parse(text: &str) -> (Option, &str) - where - Self: Sized; -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum FormatConversion { - Str, - Repr, - Ascii, - Bytes, -} - -impl FormatParse for FormatConversion { - fn parse(text: &str) -> (Option, &str) { - let Some(conversion) = Self::from_string(text) else { - return (None, text); - }; - let mut chars = text.chars(); - chars.next(); // Consume the bang - chars.next(); // Consume one r,s,a char - (Some(conversion), chars.as_str()) - } -} - -impl FormatConversion { - pub fn from_char(c: char) -> Option { - match c { - 's' => Some(FormatConversion::Str), - 'r' => Some(FormatConversion::Repr), - 'a' => Some(FormatConversion::Ascii), - 'b' => Some(FormatConversion::Bytes), - _ => None, - } - } - - fn from_string(text: &str) -> Option { - let mut chars = text.chars(); - if chars.next() != Some('!') { - return None; - } - - FormatConversion::from_char(chars.next()?) - } -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum FormatAlign { - Left, - Right, - AfterSign, - Center, -} - -impl FormatAlign { - fn from_char(c: char) -> Option { - match c { - '<' => Some(FormatAlign::Left), - '>' => Some(FormatAlign::Right), - '=' => Some(FormatAlign::AfterSign), - '^' => Some(FormatAlign::Center), - _ => None, - } - } -} - -impl FormatParse for FormatAlign { - fn parse(text: &str) -> (Option, &str) { - let mut chars = text.chars(); - if let Some(maybe_align) = chars.next().and_then(Self::from_char) { - (Some(maybe_align), chars.as_str()) - } else { - (None, text) - } - } -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum FormatSign { - Plus, - Minus, - MinusOrSpace, -} - -impl FormatParse for FormatSign { - fn parse(text: &str) -> (Option, &str) { - let mut chars = text.chars(); - match chars.next() { - Some('-') => (Some(Self::Minus), chars.as_str()), - Some('+') => (Some(Self::Plus), chars.as_str()), - Some(' ') => (Some(Self::MinusOrSpace), chars.as_str()), - _ => (None, text), - } - } -} - -#[derive(Debug, PartialEq)] -pub enum FormatGrouping { - Comma, - Underscore, -} - -impl FormatParse for FormatGrouping { - fn parse(text: &str) -> (Option, &str) { - let mut chars = text.chars(); - match chars.next() { - Some('_') => (Some(Self::Underscore), chars.as_str()), - Some(',') => (Some(Self::Comma), chars.as_str()), - _ => (None, text), - } - } -} - -#[derive(Debug, PartialEq)] -pub enum FormatType { - String, - Binary, - Character, - Decimal, - Octal, - Number(Case), - Hex(Case), - Exponent(Case), - GeneralFormat(Case), - FixedPoint(Case), - Percentage, -} - -impl From<&FormatType> for char { - fn from(from: &FormatType) -> char { - match from { - FormatType::String => 's', - FormatType::Binary => 'b', - FormatType::Character => 'c', - FormatType::Decimal => 'd', - FormatType::Octal => 'o', - FormatType::Number(Case::Lower) => 'n', - FormatType::Number(Case::Upper) => 'N', - FormatType::Hex(Case::Lower) => 'x', - FormatType::Hex(Case::Upper) => 'X', - FormatType::Exponent(Case::Lower) => 'e', - FormatType::Exponent(Case::Upper) => 'E', - FormatType::GeneralFormat(Case::Lower) => 'g', - FormatType::GeneralFormat(Case::Upper) => 'G', - FormatType::FixedPoint(Case::Lower) => 'f', - FormatType::FixedPoint(Case::Upper) => 'F', - FormatType::Percentage => '%', - } - } -} - -impl FormatParse for FormatType { - fn parse(text: &str) -> (Option, &str) { - let mut chars = text.chars(); - match chars.next() { - Some('s') => (Some(Self::String), chars.as_str()), - Some('b') => (Some(Self::Binary), chars.as_str()), - Some('c') => (Some(Self::Character), chars.as_str()), - Some('d') => (Some(Self::Decimal), chars.as_str()), - Some('o') => (Some(Self::Octal), chars.as_str()), - Some('n') => (Some(Self::Number(Case::Lower)), chars.as_str()), - Some('N') => (Some(Self::Number(Case::Upper)), chars.as_str()), - Some('x') => (Some(Self::Hex(Case::Lower)), chars.as_str()), - Some('X') => (Some(Self::Hex(Case::Upper)), chars.as_str()), - Some('e') => (Some(Self::Exponent(Case::Lower)), chars.as_str()), - Some('E') => (Some(Self::Exponent(Case::Upper)), chars.as_str()), - Some('f') => (Some(Self::FixedPoint(Case::Lower)), chars.as_str()), - Some('F') => (Some(Self::FixedPoint(Case::Upper)), chars.as_str()), - Some('g') => (Some(Self::GeneralFormat(Case::Lower)), chars.as_str()), - Some('G') => (Some(Self::GeneralFormat(Case::Upper)), chars.as_str()), - Some('%') => (Some(Self::Percentage), chars.as_str()), - _ => (None, text), - } - } -} - -#[derive(Debug, PartialEq)] -pub struct FormatSpec { - conversion: Option, - fill: Option, - align: Option, - sign: Option, - alternate_form: bool, - width: Option, - grouping_option: Option, - precision: Option, - format_type: Option, -} - -fn get_num_digits(text: &str) -> usize { - for (index, character) in text.char_indices() { - if !character.is_ascii_digit() { - return index; - } - } - text.len() -} - -fn parse_fill_and_align(text: &str) -> (Option, Option, &str) { - let char_indices: Vec<(usize, char)> = text.char_indices().take(3).collect(); - if char_indices.is_empty() { - (None, None, text) - } else if char_indices.len() == 1 { - let (maybe_align, remaining) = FormatAlign::parse(text); - (None, maybe_align, remaining) - } else { - let (maybe_align, remaining) = FormatAlign::parse(&text[char_indices[1].0..]); - if maybe_align.is_some() { - (Some(char_indices[0].1), maybe_align, remaining) - } else { - let (only_align, only_align_remaining) = FormatAlign::parse(text); - (None, only_align, only_align_remaining) - } - } -} - -fn parse_number(text: &str) -> Result<(Option, &str), FormatSpecError> { - let num_digits: usize = get_num_digits(text); - if num_digits == 0 { - return Ok((None, text)); - } - if let Ok(num) = text[..num_digits].parse::() { - Ok((Some(num), &text[num_digits..])) - } else { - // NOTE: this condition is different from CPython - Err(FormatSpecError::DecimalDigitsTooMany) - } -} - -fn parse_alternate_form(text: &str) -> (bool, &str) { - let mut chars = text.chars(); - match chars.next() { - Some('#') => (true, chars.as_str()), - _ => (false, text), - } -} - -fn parse_zero(text: &str) -> (bool, &str) { - let mut chars = text.chars(); - match chars.next() { - Some('0') => (true, chars.as_str()), - _ => (false, text), - } -} - -fn parse_precision(text: &str) -> Result<(Option, &str), FormatSpecError> { - let mut chars = text.chars(); - Ok(match chars.next() { - Some('.') => { - let (size, remaining) = parse_number(chars.as_str())?; - if let Some(size) = size { - if size > i32::MAX as usize { - return Err(FormatSpecError::PrecisionTooBig); - } - (Some(size), remaining) - } else { - (None, text) - } - } - _ => (None, text), - }) -} - -impl FormatSpec { - pub fn parse(text: &str) -> Result { - // get_integer in CPython - let (conversion, text) = FormatConversion::parse(text); - let (mut fill, mut align, text) = parse_fill_and_align(text); - let (sign, text) = FormatSign::parse(text); - let (alternate_form, text) = parse_alternate_form(text); - let (zero, text) = parse_zero(text); - let (width, text) = parse_number(text)?; - let (grouping_option, text) = FormatGrouping::parse(text); - let (precision, text) = parse_precision(text)?; - let (format_type, text) = FormatType::parse(text); - if !text.is_empty() { - return Err(FormatSpecError::InvalidFormatSpecifier); - } - - if zero && fill.is_none() { - fill.replace('0'); - align = align.or(Some(FormatAlign::AfterSign)); - } - - Ok(FormatSpec { - conversion, - fill, - align, - sign, - alternate_form, - width, - grouping_option, - precision, - format_type, - }) - } - - fn compute_fill_string(fill_char: char, fill_chars_needed: i32) -> String { - (0..fill_chars_needed) - .map(|_| fill_char) - .collect::() - } - - fn add_magnitude_separators_for_char( - magnitude_str: String, - inter: i32, - sep: char, - disp_digit_cnt: i32, - ) -> String { - // Don't add separators to the floating decimal point of numbers - let mut parts = magnitude_str.splitn(2, '.'); - let magnitude_int_str = parts.next().unwrap().to_string(); - let dec_digit_cnt = magnitude_str.len() as i32 - magnitude_int_str.len() as i32; - let int_digit_cnt = disp_digit_cnt - dec_digit_cnt; - let mut result = FormatSpec::separate_integer(magnitude_int_str, inter, sep, int_digit_cnt); - if let Some(part) = parts.next() { - result.push_str(&format!(".{part}")) - } - result - } - - fn separate_integer( - magnitude_str: String, - inter: i32, - sep: char, - disp_digit_cnt: i32, - ) -> String { - let magnitude_len = magnitude_str.len() as i32; - let offset = (disp_digit_cnt % (inter + 1) == 0) as i32; - let disp_digit_cnt = disp_digit_cnt + offset; - let pad_cnt = disp_digit_cnt - magnitude_len; - let sep_cnt = disp_digit_cnt / (inter + 1); - let diff = pad_cnt - sep_cnt; - if pad_cnt > 0 && diff > 0 { - // separate with 0 padding - let padding = "0".repeat(diff as usize); - let padded_num = format!("{padding}{magnitude_str}"); - FormatSpec::insert_separator(padded_num, inter, sep, sep_cnt) - } else { - // separate without padding - let sep_cnt = (magnitude_len - 1) / inter; - FormatSpec::insert_separator(magnitude_str, inter, sep, sep_cnt) - } - } - - fn insert_separator(mut magnitude_str: String, inter: i32, sep: char, sep_cnt: i32) -> String { - let magnitude_len = magnitude_str.len() as i32; - for i in 1..sep_cnt + 1 { - magnitude_str.insert((magnitude_len - inter * i) as usize, sep); - } - magnitude_str - } - - fn validate_format(&self, default_format_type: FormatType) -> Result<(), FormatSpecError> { - let format_type = self.format_type.as_ref().unwrap_or(&default_format_type); - match (&self.grouping_option, format_type) { - ( - Some(FormatGrouping::Comma), - FormatType::String - | FormatType::Character - | FormatType::Binary - | FormatType::Octal - | FormatType::Hex(_) - | FormatType::Number(_), - ) => { - let ch = char::from(format_type); - Err(FormatSpecError::UnspecifiedFormat(',', ch)) - } - ( - Some(FormatGrouping::Underscore), - FormatType::String | FormatType::Character | FormatType::Number(_), - ) => { - let ch = char::from(format_type); - Err(FormatSpecError::UnspecifiedFormat('_', ch)) - } - _ => Ok(()), - } - } - - fn get_separator_interval(&self) -> usize { - match self.format_type { - Some(FormatType::Binary | FormatType::Octal | FormatType::Hex(_)) => 4, - Some(FormatType::Decimal | FormatType::Number(_) | FormatType::FixedPoint(_)) => 3, - None => 3, - _ => panic!("Separators only valid for numbers!"), - } - } - - fn add_magnitude_separators(&self, magnitude_str: String, prefix: &str) -> String { - match &self.grouping_option { - Some(fg) => { - let sep = match fg { - FormatGrouping::Comma => ',', - FormatGrouping::Underscore => '_', - }; - let inter = self.get_separator_interval().try_into().unwrap(); - let magnitude_len = magnitude_str.len(); - let width = self.width.unwrap_or(magnitude_len) as i32 - prefix.len() as i32; - let disp_digit_cnt = cmp::max(width, magnitude_len as i32); - FormatSpec::add_magnitude_separators_for_char( - magnitude_str, - inter, - sep, - disp_digit_cnt, - ) - } - None => magnitude_str, - } - } - - pub fn format_bool(&self, input: bool) -> Result { - let x = u8::from(input); - match &self.format_type { - Some( - FormatType::Binary - | FormatType::Decimal - | FormatType::Octal - | FormatType::Number(Case::Lower) - | FormatType::Hex(_) - | FormatType::GeneralFormat(_) - | FormatType::Character, - ) => self.format_int(&BigInt::from_u8(x).unwrap()), - Some(FormatType::Exponent(_) | FormatType::FixedPoint(_) | FormatType::Percentage) => { - self.format_float(x as f64) - } - None => { - let first_letter = (input.to_string().as_bytes()[0] as char).to_uppercase(); - Ok(first_letter.collect::() + &input.to_string()[1..]) - } - _ => Err(FormatSpecError::InvalidFormatSpecifier), - } - } - - pub fn format_float(&self, num: f64) -> Result { - self.validate_format(FormatType::FixedPoint(Case::Lower))?; - let precision = self.precision.unwrap_or(6); - let magnitude = num.abs(); - let raw_magnitude_str: Result = match &self.format_type { - Some(FormatType::FixedPoint(case)) => Ok(float::format_fixed( - precision, - magnitude, - *case, - self.alternate_form, - )), - Some(FormatType::Decimal) - | Some(FormatType::Binary) - | Some(FormatType::Octal) - | Some(FormatType::Hex(_)) - | Some(FormatType::String) - | Some(FormatType::Character) - | Some(FormatType::Number(Case::Upper)) => { - let ch = char::from(self.format_type.as_ref().unwrap()); - Err(FormatSpecError::UnknownFormatCode(ch, "float")) - } - Some(FormatType::GeneralFormat(case)) | Some(FormatType::Number(case)) => { - let precision = if precision == 0 { 1 } else { precision }; - Ok(float::format_general( - precision, - magnitude, - *case, - self.alternate_form, - false, - )) - } - Some(FormatType::Exponent(case)) => Ok(float::format_exponent( - precision, - magnitude, - *case, - self.alternate_form, - )), - Some(FormatType::Percentage) => match magnitude { - magnitude if magnitude.is_nan() => Ok("nan%".to_owned()), - magnitude if magnitude.is_infinite() => Ok("inf%".to_owned()), - _ => { - let result = format!("{:.*}", precision, magnitude * 100.0); - let point = float::decimal_point_or_empty(precision, self.alternate_form); - Ok(format!("{result}{point}%")) - } - }, - None => match magnitude { - magnitude if magnitude.is_nan() => Ok("nan".to_owned()), - magnitude if magnitude.is_infinite() => Ok("inf".to_owned()), - _ => match self.precision { - Some(precision) => Ok(float::format_general( - precision, - magnitude, - Case::Lower, - self.alternate_form, - true, - )), - None => Ok(float::to_string(magnitude)), - }, - }, - }; - let format_sign = self.sign.unwrap_or(FormatSign::Minus); - let sign_str = if num.is_sign_negative() && !num.is_nan() { - "-" - } else { - match format_sign { - FormatSign::Plus => "+", - FormatSign::Minus => "", - FormatSign::MinusOrSpace => " ", - } - }; - let magnitude_str = self.add_magnitude_separators(raw_magnitude_str?, sign_str); - self.format_sign_and_align(&AsciiStr::new(&magnitude_str), sign_str, FormatAlign::Right) - } - - #[inline] - fn format_int_radix(&self, magnitude: BigInt, radix: u32) -> Result { - match self.precision { - Some(_) => Err(FormatSpecError::PrecisionNotAllowed), - None => Ok(magnitude.to_str_radix(radix)), - } - } - - pub fn format_int(&self, num: &BigInt) -> Result { - self.validate_format(FormatType::Decimal)?; - let magnitude = num.abs(); - let prefix = if self.alternate_form { - match self.format_type { - Some(FormatType::Binary) => "0b", - Some(FormatType::Octal) => "0o", - Some(FormatType::Hex(Case::Lower)) => "0x", - Some(FormatType::Hex(Case::Upper)) => "0X", - _ => "", - } - } else { - "" - }; - let raw_magnitude_str = match self.format_type { - Some(FormatType::Binary) => self.format_int_radix(magnitude, 2), - Some(FormatType::Decimal) => self.format_int_radix(magnitude, 10), - Some(FormatType::Octal) => self.format_int_radix(magnitude, 8), - Some(FormatType::Hex(Case::Lower)) => self.format_int_radix(magnitude, 16), - Some(FormatType::Hex(Case::Upper)) => match self.precision { - Some(_) => Err(FormatSpecError::PrecisionNotAllowed), - None => { - let mut result = magnitude.to_str_radix(16); - result.make_ascii_uppercase(); - Ok(result) - } - }, - Some(FormatType::Number(Case::Lower)) => self.format_int_radix(magnitude, 10), - Some(FormatType::Number(Case::Upper)) => { - Err(FormatSpecError::UnknownFormatCode('N', "int")) - } - Some(FormatType::String) => Err(FormatSpecError::UnknownFormatCode('s', "int")), - Some(FormatType::Character) => match (self.sign, self.alternate_form) { - (Some(_), _) => Err(FormatSpecError::NotAllowed("Sign")), - (_, true) => Err(FormatSpecError::NotAllowed("Alternate form (#)")), - (_, _) => match num.to_u32() { - Some(n) if n <= 0x10ffff => Ok(std::char::from_u32(n).unwrap().to_string()), - Some(_) | None => Err(FormatSpecError::CodeNotInRange), - }, - }, - Some(FormatType::GeneralFormat(_)) - | Some(FormatType::FixedPoint(_)) - | Some(FormatType::Exponent(_)) - | Some(FormatType::Percentage) => match num.to_f64() { - Some(float) => return self.format_float(float), - _ => Err(FormatSpecError::UnableToConvert), - }, - None => self.format_int_radix(magnitude, 10), - }?; - let format_sign = self.sign.unwrap_or(FormatSign::Minus); - let sign_str = match num.sign() { - Sign::Minus => "-", - _ => match format_sign { - FormatSign::Plus => "+", - FormatSign::Minus => "", - FormatSign::MinusOrSpace => " ", - }, - }; - let sign_prefix = format!("{sign_str}{prefix}"); - let magnitude_str = self.add_magnitude_separators(raw_magnitude_str, &sign_prefix); - self.format_sign_and_align( - &AsciiStr::new(&magnitude_str), - &sign_prefix, - FormatAlign::Right, - ) - } - - pub fn format_string(&self, s: &T) -> Result - where - T: CharLen + Deref, - { - self.validate_format(FormatType::String)?; - match self.format_type { - Some(FormatType::String) | None => self - .format_sign_and_align(s, "", FormatAlign::Left) - .map(|mut value| { - if let Some(precision) = self.precision { - value.truncate(precision); - } - value - }), - _ => { - let ch = char::from(self.format_type.as_ref().unwrap()); - Err(FormatSpecError::UnknownFormatCode(ch, "str")) - } - } - } - - fn format_sign_and_align( - &self, - magnitude_str: &T, - sign_str: &str, - default_align: FormatAlign, - ) -> Result - where - T: CharLen + Deref, - { - let align = self.align.unwrap_or(default_align); - - let num_chars = magnitude_str.char_len(); - let fill_char = self.fill.unwrap_or(' '); - let fill_chars_needed: i32 = self.width.map_or(0, |w| { - cmp::max(0, (w as i32) - (num_chars as i32) - (sign_str.len() as i32)) - }); - - let magnitude_str = magnitude_str.deref(); - Ok(match align { - FormatAlign::Left => format!( - "{}{}{}", - sign_str, - magnitude_str, - FormatSpec::compute_fill_string(fill_char, fill_chars_needed) - ), - FormatAlign::Right => format!( - "{}{}{}", - FormatSpec::compute_fill_string(fill_char, fill_chars_needed), - sign_str, - magnitude_str - ), - FormatAlign::AfterSign => format!( - "{}{}{}", - sign_str, - FormatSpec::compute_fill_string(fill_char, fill_chars_needed), - magnitude_str - ), - FormatAlign::Center => { - let left_fill_chars_needed = fill_chars_needed / 2; - let right_fill_chars_needed = fill_chars_needed - left_fill_chars_needed; - let left_fill_string = - FormatSpec::compute_fill_string(fill_char, left_fill_chars_needed); - let right_fill_string = - FormatSpec::compute_fill_string(fill_char, right_fill_chars_needed); - format!("{left_fill_string}{sign_str}{magnitude_str}{right_fill_string}") - } - }) - } -} - -pub trait CharLen { - /// Returns the number of characters in the text - fn char_len(&self) -> usize; -} - -struct AsciiStr<'a> { - inner: &'a str, -} - -impl<'a> AsciiStr<'a> { - fn new(inner: &'a str) -> Self { - Self { inner } - } -} - -impl CharLen for AsciiStr<'_> { - fn char_len(&self) -> usize { - self.inner.len() - } -} - -impl Deref for AsciiStr<'_> { - type Target = str; - fn deref(&self) -> &Self::Target { - self.inner - } -} - -#[derive(Debug, PartialEq)] -pub enum FormatSpecError { - DecimalDigitsTooMany, - PrecisionTooBig, - InvalidFormatSpecifier, - UnspecifiedFormat(char, char), - UnknownFormatCode(char, &'static str), - PrecisionNotAllowed, - NotAllowed(&'static str), - UnableToConvert, - CodeNotInRange, - NotImplemented(char, &'static str), -} - -#[derive(Debug, PartialEq)] -pub enum FormatParseError { - UnmatchedBracket, - MissingStartBracket, - UnescapedStartBracketInLiteral, - InvalidFormatSpecifier, - UnknownConversion, - EmptyAttribute, - MissingRightBracket, - InvalidCharacterAfterRightBracket, -} - -impl FromStr for FormatSpec { - type Err = FormatSpecError; - fn from_str(s: &str) -> Result { - FormatSpec::parse(s) - } -} - -#[derive(Debug, PartialEq)] -pub enum FieldNamePart { - Attribute(String), - Index(usize), - StringIndex(String), -} - -impl FieldNamePart { - fn parse_part( - chars: &mut impl PeekingNext, - ) -> Result, FormatParseError> { - chars - .next() - .map(|ch| match ch { - '.' => { - let mut attribute = String::new(); - for ch in chars.peeking_take_while(|ch| *ch != '.' && *ch != '[') { - attribute.push(ch); - } - if attribute.is_empty() { - Err(FormatParseError::EmptyAttribute) - } else { - Ok(FieldNamePart::Attribute(attribute)) - } - } - '[' => { - let mut index = String::new(); - for ch in chars { - if ch == ']' { - return if index.is_empty() { - Err(FormatParseError::EmptyAttribute) - } else if let Ok(index) = index.parse::() { - Ok(FieldNamePart::Index(index)) - } else { - Ok(FieldNamePart::StringIndex(index)) - }; - } - index.push(ch); - } - Err(FormatParseError::MissingRightBracket) - } - _ => Err(FormatParseError::InvalidCharacterAfterRightBracket), - }) - .transpose() - } -} - -#[derive(Debug, PartialEq)] -pub enum FieldType { - Auto, - Index(usize), - Keyword(String), -} - -#[derive(Debug, PartialEq)] -pub struct FieldName { - pub field_type: FieldType, - pub parts: Vec, -} - -impl FieldName { - pub fn parse(text: &str) -> Result { - let mut chars = text.chars().peekable(); - let mut first = String::new(); - for ch in chars.peeking_take_while(|ch| *ch != '.' && *ch != '[') { - first.push(ch); - } - - let field_type = if first.is_empty() { - FieldType::Auto - } else if let Ok(index) = first.parse::() { - FieldType::Index(index) - } else { - FieldType::Keyword(first) - }; - - let mut parts = Vec::new(); - while let Some(part) = FieldNamePart::parse_part(&mut chars)? { - parts.push(part) - } - - Ok(FieldName { field_type, parts }) - } -} - -#[derive(Debug, PartialEq)] -pub enum FormatPart { - Field { - field_name: String, - conversion_spec: Option, - format_spec: String, - }, - Literal(String), -} - -#[derive(Debug, PartialEq)] -pub struct FormatString { - pub format_parts: Vec, -} - -impl FormatString { - fn parse_literal_single(text: &str) -> Result<(char, &str), FormatParseError> { - let mut chars = text.chars(); - // This should never be called with an empty str - let first_char = chars.next().unwrap(); - // isn't this detectable only with bytes operation? - if first_char == '{' || first_char == '}' { - let maybe_next_char = chars.next(); - // if we see a bracket, it has to be escaped by doubling up to be in a literal - return if maybe_next_char.is_none() || maybe_next_char.unwrap() != first_char { - Err(FormatParseError::UnescapedStartBracketInLiteral) - } else { - Ok((first_char, chars.as_str())) - }; - } - Ok((first_char, chars.as_str())) - } - - fn parse_literal(text: &str) -> Result<(FormatPart, &str), FormatParseError> { - let mut cur_text = text; - let mut result_string = String::new(); - while !cur_text.is_empty() { - match FormatString::parse_literal_single(cur_text) { - Ok((next_char, remaining)) => { - result_string.push(next_char); - cur_text = remaining; - } - Err(err) => { - return if !result_string.is_empty() { - Ok((FormatPart::Literal(result_string), cur_text)) - } else { - Err(err) - }; - } - } - } - Ok((FormatPart::Literal(result_string), "")) - } - - fn parse_part_in_brackets(text: &str) -> Result { - let parts: Vec<&str> = text.splitn(2, ':').collect(); - // before the comma is a keyword or arg index, after the comma is maybe a spec. - let arg_part = parts[0]; - - let format_spec = if parts.len() > 1 { - parts[1].to_owned() - } else { - String::new() - }; - - // On parts[0] can still be the conversion (!r, !s, !a) - let parts: Vec<&str> = arg_part.splitn(2, '!').collect(); - // before the bang is a keyword or arg index, after the comma is maybe a conversion spec. - let arg_part = parts[0]; - - let conversion_spec = parts - .get(1) - .map(|conversion| { - // conversions are only every one character - conversion - .chars() - .exactly_one() - .map_err(|_| FormatParseError::UnknownConversion) - }) - .transpose()?; - - Ok(FormatPart::Field { - field_name: arg_part.to_owned(), - conversion_spec, - format_spec, - }) - } - - fn parse_spec(text: &str) -> Result<(FormatPart, &str), FormatParseError> { - let mut nested = false; - let mut end_bracket_pos = None; - let mut left = String::new(); - - // There may be one layer nesting brackets in spec - for (idx, c) in text.char_indices() { - if idx == 0 { - if c != '{' { - return Err(FormatParseError::MissingStartBracket); - } - } else if c == '{' { - if nested { - return Err(FormatParseError::InvalidFormatSpecifier); - } else { - nested = true; - left.push(c); - continue; - } - } else if c == '}' { - if nested { - nested = false; - left.push(c); - continue; - } else { - end_bracket_pos = Some(idx); - break; - } - } else { - left.push(c); - } - } - if let Some(pos) = end_bracket_pos { - let (_, right) = text.split_at(pos); - let format_part = FormatString::parse_part_in_brackets(&left)?; - Ok((format_part, &right[1..])) - } else { - Err(FormatParseError::UnmatchedBracket) - } - } -} - -pub trait FromTemplate<'a>: Sized { - type Err; - fn from_str(s: &'a str) -> Result; -} - -impl<'a> FromTemplate<'a> for FormatString { - type Err = FormatParseError; - - fn from_str(text: &'a str) -> Result { - let mut cur_text: &str = text; - let mut parts: Vec = Vec::new(); - while !cur_text.is_empty() { - // Try to parse both literals and bracketed format parts until we - // run out of text - cur_text = FormatString::parse_literal(cur_text) - .or_else(|_| FormatString::parse_spec(cur_text)) - .map(|(part, new_text)| { - parts.push(part); - new_text - })?; - } - Ok(FormatString { - format_parts: parts, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_fill_and_align() { - assert_eq!( - parse_fill_and_align(" <"), - (Some(' '), Some(FormatAlign::Left), "") - ); - assert_eq!( - parse_fill_and_align(" <22"), - (Some(' '), Some(FormatAlign::Left), "22") - ); - assert_eq!( - parse_fill_and_align("<22"), - (None, Some(FormatAlign::Left), "22") - ); - assert_eq!( - parse_fill_and_align(" ^^"), - (Some(' '), Some(FormatAlign::Center), "^") - ); - assert_eq!( - parse_fill_and_align("==="), - (Some('='), Some(FormatAlign::AfterSign), "=") - ); - } - - #[test] - fn test_width_only() { - let expected = Ok(FormatSpec { - conversion: None, - fill: None, - align: None, - sign: None, - alternate_form: false, - width: Some(33), - grouping_option: None, - precision: None, - format_type: None, - }); - assert_eq!(FormatSpec::parse("33"), expected); - } - - #[test] - fn test_fill_and_width() { - let expected = Ok(FormatSpec { - conversion: None, - fill: Some('<'), - align: Some(FormatAlign::Right), - sign: None, - alternate_form: false, - width: Some(33), - grouping_option: None, - precision: None, - format_type: None, - }); - assert_eq!(FormatSpec::parse("<>33"), expected); - } - - #[test] - fn test_all() { - let expected = Ok(FormatSpec { - conversion: None, - fill: Some('<'), - align: Some(FormatAlign::Right), - sign: Some(FormatSign::Minus), - alternate_form: true, - width: Some(23), - grouping_option: Some(FormatGrouping::Comma), - precision: Some(11), - format_type: Some(FormatType::Binary), - }); - assert_eq!(FormatSpec::parse("<>-#23,.11b"), expected); - } - - fn format_bool(text: &str, value: bool) -> Result { - FormatSpec::parse(text).and_then(|spec| spec.format_bool(value)) - } - - #[test] - fn test_format_bool() { - assert_eq!(format_bool("b", true), Ok("1".to_owned())); - assert_eq!(format_bool("b", false), Ok("0".to_owned())); - assert_eq!(format_bool("d", true), Ok("1".to_owned())); - assert_eq!(format_bool("d", false), Ok("0".to_owned())); - assert_eq!(format_bool("o", true), Ok("1".to_owned())); - assert_eq!(format_bool("o", false), Ok("0".to_owned())); - assert_eq!(format_bool("n", true), Ok("1".to_owned())); - assert_eq!(format_bool("n", false), Ok("0".to_owned())); - assert_eq!(format_bool("x", true), Ok("1".to_owned())); - assert_eq!(format_bool("x", false), Ok("0".to_owned())); - assert_eq!(format_bool("X", true), Ok("1".to_owned())); - assert_eq!(format_bool("X", false), Ok("0".to_owned())); - assert_eq!(format_bool("g", true), Ok("1".to_owned())); - assert_eq!(format_bool("g", false), Ok("0".to_owned())); - assert_eq!(format_bool("G", true), Ok("1".to_owned())); - assert_eq!(format_bool("G", false), Ok("0".to_owned())); - assert_eq!(format_bool("c", true), Ok("\x01".to_owned())); - assert_eq!(format_bool("c", false), Ok("\x00".to_owned())); - assert_eq!(format_bool("e", true), Ok("1.000000e+00".to_owned())); - assert_eq!(format_bool("e", false), Ok("0.000000e+00".to_owned())); - assert_eq!(format_bool("E", true), Ok("1.000000E+00".to_owned())); - assert_eq!(format_bool("E", false), Ok("0.000000E+00".to_owned())); - assert_eq!(format_bool("f", true), Ok("1.000000".to_owned())); - assert_eq!(format_bool("f", false), Ok("0.000000".to_owned())); - assert_eq!(format_bool("F", true), Ok("1.000000".to_owned())); - assert_eq!(format_bool("F", false), Ok("0.000000".to_owned())); - assert_eq!(format_bool("%", true), Ok("100.000000%".to_owned())); - assert_eq!(format_bool("%", false), Ok("0.000000%".to_owned())); - } - - #[test] - fn test_format_int() { - assert_eq!( - FormatSpec::parse("d") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("16".to_owned()) - ); - assert_eq!( - FormatSpec::parse("x") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("10".to_owned()) - ); - assert_eq!( - FormatSpec::parse("b") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("10000".to_owned()) - ); - assert_eq!( - FormatSpec::parse("o") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("20".to_owned()) - ); - assert_eq!( - FormatSpec::parse("+d") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("+16".to_owned()) - ); - assert_eq!( - FormatSpec::parse("^ 5d") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Minus, b"\x10")), - Ok(" -16 ".to_owned()) - ); - assert_eq!( - FormatSpec::parse("0>+#10x") - .unwrap() - .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), - Ok("00000+0x10".to_owned()) - ); - } - - #[test] - fn test_format_int_sep() { - let spec = FormatSpec::parse(",").expect(""); - assert_eq!(spec.grouping_option, Some(FormatGrouping::Comma)); - assert_eq!( - spec.format_int(&BigInt::from_str("1234567890123456789012345678").unwrap()), - Ok("1,234,567,890,123,456,789,012,345,678".to_owned()) - ); - } - - #[test] - fn test_format_parse() { - let expected = Ok(FormatString { - format_parts: vec![ - FormatPart::Literal("abcd".to_owned()), - FormatPart::Field { - field_name: "1".to_owned(), - conversion_spec: None, - format_spec: String::new(), - }, - FormatPart::Literal(":".to_owned()), - FormatPart::Field { - field_name: "key".to_owned(), - conversion_spec: None, - format_spec: String::new(), - }, - ], - }); - - assert_eq!(FormatString::from_str("abcd{1}:{key}"), expected); - } - - #[test] - fn test_format_parse_multi_byte_char() { - assert!(FormatString::from_str("{a:%ЫйЯЧ}").is_ok()); - } - - #[test] - fn test_format_parse_fail() { - assert_eq!( - FormatString::from_str("{s"), - Err(FormatParseError::UnmatchedBracket) - ); - } - - #[test] - fn test_format_parse_escape() { - let expected = Ok(FormatString { - format_parts: vec![ - FormatPart::Literal("{".to_owned()), - FormatPart::Field { - field_name: "key".to_owned(), - conversion_spec: None, - format_spec: String::new(), - }, - FormatPart::Literal("}ddfe".to_owned()), - ], - }); - - assert_eq!(FormatString::from_str("{{{key}}}ddfe"), expected); - } - - #[test] - fn test_format_invalid_specification() { - assert_eq!( - FormatSpec::parse("%3"), - Err(FormatSpecError::InvalidFormatSpecifier) - ); - assert_eq!( - FormatSpec::parse(".2fa"), - Err(FormatSpecError::InvalidFormatSpecifier) - ); - assert_eq!( - FormatSpec::parse("ds"), - Err(FormatSpecError::InvalidFormatSpecifier) - ); - assert_eq!( - FormatSpec::parse("x+"), - Err(FormatSpecError::InvalidFormatSpecifier) - ); - assert_eq!( - FormatSpec::parse("b4"), - Err(FormatSpecError::InvalidFormatSpecifier) - ); - assert_eq!( - FormatSpec::parse("o!"), - Err(FormatSpecError::InvalidFormatSpecifier) - ); - assert_eq!( - FormatSpec::parse("d "), - Err(FormatSpecError::InvalidFormatSpecifier) - ); - } - - #[test] - fn test_parse_field_name() { - assert_eq!( - FieldName::parse(""), - Ok(FieldName { - field_type: FieldType::Auto, - parts: Vec::new(), - }) - ); - assert_eq!( - FieldName::parse("0"), - Ok(FieldName { - field_type: FieldType::Index(0), - parts: Vec::new(), - }) - ); - assert_eq!( - FieldName::parse("key"), - Ok(FieldName { - field_type: FieldType::Keyword("key".to_owned()), - parts: Vec::new(), - }) - ); - assert_eq!( - FieldName::parse("key.attr[0][string]"), - Ok(FieldName { - field_type: FieldType::Keyword("key".to_owned()), - parts: vec![ - FieldNamePart::Attribute("attr".to_owned()), - FieldNamePart::Index(0), - FieldNamePart::StringIndex("string".to_owned()) - ], - }) - ); - assert_eq!( - FieldName::parse("key.."), - Err(FormatParseError::EmptyAttribute) - ); - assert_eq!( - FieldName::parse("key[]"), - Err(FormatParseError::EmptyAttribute) - ); - assert_eq!( - FieldName::parse("key["), - Err(FormatParseError::MissingRightBracket) - ); - assert_eq!( - FieldName::parse("key[0]after"), - Err(FormatParseError::InvalidCharacterAfterRightBracket) - ); - } -} diff --git a/format/src/lib.rs b/format/src/lib.rs deleted file mode 100644 index e15074ba..00000000 --- a/format/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub use crate::format::*; - -pub mod cformat; -mod format; diff --git a/literal/Cargo.toml b/literal/Cargo.toml index 4133d97a..7e9ae443 100644 --- a/literal/Cargo.toml +++ b/literal/Cargo.toml @@ -8,9 +8,12 @@ repository = "https://github.com/RustPython/Parser/" license = "MIT" [dependencies] +bitflags = { workspace = true } hexf-parse = "0.2.1" is-macro.workspace = true +itertools = { workspace = true } lexical-parse-float = { version = "0.8.0", features = ["format"] } +num-bigint = { workspace = true } num-traits = { workspace = true } unic-ucd-category = "0.9" diff --git a/format/src/cformat.rs b/literal/src/cformat.rs similarity index 99% rename from format/src/cformat.rs rename to literal/src/cformat.rs index 8519bbd6..7a07f531 100644 --- a/format/src/cformat.rs +++ b/literal/src/cformat.rs @@ -2,13 +2,13 @@ //! as per the [Python Docs](https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting). use bitflags::bitflags; use num_traits::Signed; -use rustpython_literal::{float, format::Case}; use std::{ cmp, fmt, iter::{Enumerate, Peekable}, str::FromStr, }; +use crate::{float, Case}; use num_bigint::{BigInt, Sign}; #[derive(Debug, PartialEq)] @@ -690,9 +690,7 @@ impl FromStr for CFormatString { } impl CFormatString { - pub(crate) fn parse>( - iter: &mut ParseIter, - ) -> Result { + pub fn parse>(iter: &mut ParseIter) -> Result { let mut parts = vec![]; let mut literal = String::new(); let mut part_index = 0; diff --git a/literal/src/float.rs b/literal/src/float.rs index 5c14fcbc..bfd7d43e 100644 --- a/literal/src/float.rs +++ b/literal/src/float.rs @@ -1,4 +1,4 @@ -use crate::format::Case; +use crate::Case; use num_traits::{Float, Zero}; use std::f64; diff --git a/literal/src/format.rs b/literal/src/format.rs index 4ce21ad7..b80adc9a 100644 --- a/literal/src/format.rs +++ b/literal/src/format.rs @@ -1,5 +1,1271 @@ -#[derive(Debug, PartialEq, Eq, Clone, Copy, is_macro::Is, Hash)] -pub enum Case { - Lower, - Upper, +use itertools::{Itertools, PeekingNext}; + +use num_traits::{cast::ToPrimitive, FromPrimitive, Signed}; +use std::ops::Deref; +use std::{cmp, str::FromStr}; + +use crate::{float, Case}; +use num_bigint::{BigInt, Sign}; + +trait FormatParse { + fn parse(text: &str) -> (Option, &str) + where + Self: Sized; +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum FormatConversion { + Str, + Repr, + Ascii, + Bytes, +} + +impl FormatParse for FormatConversion { + fn parse(text: &str) -> (Option, &str) { + let Some(conversion) = Self::from_string(text) else { + return (None, text); + }; + let mut chars = text.chars(); + chars.next(); // Consume the bang + chars.next(); // Consume one r,s,a char + (Some(conversion), chars.as_str()) + } +} + +impl FormatConversion { + pub fn from_char(c: char) -> Option { + match c { + 's' => Some(FormatConversion::Str), + 'r' => Some(FormatConversion::Repr), + 'a' => Some(FormatConversion::Ascii), + 'b' => Some(FormatConversion::Bytes), + _ => None, + } + } + + fn from_string(text: &str) -> Option { + let mut chars = text.chars(); + if chars.next() != Some('!') { + return None; + } + + FormatConversion::from_char(chars.next()?) + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum FormatAlign { + Left, + Right, + AfterSign, + Center, +} + +impl FormatAlign { + fn from_char(c: char) -> Option { + match c { + '<' => Some(FormatAlign::Left), + '>' => Some(FormatAlign::Right), + '=' => Some(FormatAlign::AfterSign), + '^' => Some(FormatAlign::Center), + _ => None, + } + } +} + +impl FormatParse for FormatAlign { + fn parse(text: &str) -> (Option, &str) { + let mut chars = text.chars(); + if let Some(maybe_align) = chars.next().and_then(Self::from_char) { + (Some(maybe_align), chars.as_str()) + } else { + (None, text) + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum FormatSign { + Plus, + Minus, + MinusOrSpace, +} + +impl FormatParse for FormatSign { + fn parse(text: &str) -> (Option, &str) { + let mut chars = text.chars(); + match chars.next() { + Some('-') => (Some(Self::Minus), chars.as_str()), + Some('+') => (Some(Self::Plus), chars.as_str()), + Some(' ') => (Some(Self::MinusOrSpace), chars.as_str()), + _ => (None, text), + } + } +} + +#[derive(Debug, PartialEq)] +pub enum FormatGrouping { + Comma, + Underscore, +} + +impl FormatParse for FormatGrouping { + fn parse(text: &str) -> (Option, &str) { + let mut chars = text.chars(); + match chars.next() { + Some('_') => (Some(Self::Underscore), chars.as_str()), + Some(',') => (Some(Self::Comma), chars.as_str()), + _ => (None, text), + } + } +} + +#[derive(Debug, PartialEq)] +pub enum FormatType { + String, + Binary, + Character, + Decimal, + Octal, + Number(Case), + Hex(Case), + Exponent(Case), + GeneralFormat(Case), + FixedPoint(Case), + Percentage, +} + +impl From<&FormatType> for char { + fn from(from: &FormatType) -> char { + match from { + FormatType::String => 's', + FormatType::Binary => 'b', + FormatType::Character => 'c', + FormatType::Decimal => 'd', + FormatType::Octal => 'o', + FormatType::Number(Case::Lower) => 'n', + FormatType::Number(Case::Upper) => 'N', + FormatType::Hex(Case::Lower) => 'x', + FormatType::Hex(Case::Upper) => 'X', + FormatType::Exponent(Case::Lower) => 'e', + FormatType::Exponent(Case::Upper) => 'E', + FormatType::GeneralFormat(Case::Lower) => 'g', + FormatType::GeneralFormat(Case::Upper) => 'G', + FormatType::FixedPoint(Case::Lower) => 'f', + FormatType::FixedPoint(Case::Upper) => 'F', + FormatType::Percentage => '%', + } + } +} + +impl FormatParse for FormatType { + fn parse(text: &str) -> (Option, &str) { + let mut chars = text.chars(); + match chars.next() { + Some('s') => (Some(Self::String), chars.as_str()), + Some('b') => (Some(Self::Binary), chars.as_str()), + Some('c') => (Some(Self::Character), chars.as_str()), + Some('d') => (Some(Self::Decimal), chars.as_str()), + Some('o') => (Some(Self::Octal), chars.as_str()), + Some('n') => (Some(Self::Number(Case::Lower)), chars.as_str()), + Some('N') => (Some(Self::Number(Case::Upper)), chars.as_str()), + Some('x') => (Some(Self::Hex(Case::Lower)), chars.as_str()), + Some('X') => (Some(Self::Hex(Case::Upper)), chars.as_str()), + Some('e') => (Some(Self::Exponent(Case::Lower)), chars.as_str()), + Some('E') => (Some(Self::Exponent(Case::Upper)), chars.as_str()), + Some('f') => (Some(Self::FixedPoint(Case::Lower)), chars.as_str()), + Some('F') => (Some(Self::FixedPoint(Case::Upper)), chars.as_str()), + Some('g') => (Some(Self::GeneralFormat(Case::Lower)), chars.as_str()), + Some('G') => (Some(Self::GeneralFormat(Case::Upper)), chars.as_str()), + Some('%') => (Some(Self::Percentage), chars.as_str()), + _ => (None, text), + } + } +} + +#[derive(Debug, PartialEq)] +pub struct FormatSpec { + conversion: Option, + fill: Option, + align: Option, + sign: Option, + alternate_form: bool, + width: Option, + grouping_option: Option, + precision: Option, + format_type: Option, +} + +fn get_num_digits(text: &str) -> usize { + for (index, character) in text.char_indices() { + if !character.is_ascii_digit() { + return index; + } + } + text.len() +} + +fn parse_fill_and_align(text: &str) -> (Option, Option, &str) { + let char_indices: Vec<(usize, char)> = text.char_indices().take(3).collect(); + if char_indices.is_empty() { + (None, None, text) + } else if char_indices.len() == 1 { + let (maybe_align, remaining) = FormatAlign::parse(text); + (None, maybe_align, remaining) + } else { + let (maybe_align, remaining) = FormatAlign::parse(&text[char_indices[1].0..]); + if maybe_align.is_some() { + (Some(char_indices[0].1), maybe_align, remaining) + } else { + let (only_align, only_align_remaining) = FormatAlign::parse(text); + (None, only_align, only_align_remaining) + } + } +} + +fn parse_number(text: &str) -> Result<(Option, &str), FormatSpecError> { + let num_digits: usize = get_num_digits(text); + if num_digits == 0 { + return Ok((None, text)); + } + if let Ok(num) = text[..num_digits].parse::() { + Ok((Some(num), &text[num_digits..])) + } else { + // NOTE: this condition is different from CPython + Err(FormatSpecError::DecimalDigitsTooMany) + } +} + +fn parse_alternate_form(text: &str) -> (bool, &str) { + let mut chars = text.chars(); + match chars.next() { + Some('#') => (true, chars.as_str()), + _ => (false, text), + } +} + +fn parse_zero(text: &str) -> (bool, &str) { + let mut chars = text.chars(); + match chars.next() { + Some('0') => (true, chars.as_str()), + _ => (false, text), + } +} + +fn parse_precision(text: &str) -> Result<(Option, &str), FormatSpecError> { + let mut chars = text.chars(); + Ok(match chars.next() { + Some('.') => { + let (size, remaining) = parse_number(chars.as_str())?; + if let Some(size) = size { + if size > i32::MAX as usize { + return Err(FormatSpecError::PrecisionTooBig); + } + (Some(size), remaining) + } else { + (None, text) + } + } + _ => (None, text), + }) +} + +impl FormatSpec { + pub fn parse(text: &str) -> Result { + // get_integer in CPython + let (conversion, text) = FormatConversion::parse(text); + let (mut fill, mut align, text) = parse_fill_and_align(text); + let (sign, text) = FormatSign::parse(text); + let (alternate_form, text) = parse_alternate_form(text); + let (zero, text) = parse_zero(text); + let (width, text) = parse_number(text)?; + let (grouping_option, text) = FormatGrouping::parse(text); + let (precision, text) = parse_precision(text)?; + let (format_type, text) = FormatType::parse(text); + if !text.is_empty() { + return Err(FormatSpecError::InvalidFormatSpecifier); + } + + if zero && fill.is_none() { + fill.replace('0'); + align = align.or(Some(FormatAlign::AfterSign)); + } + + Ok(FormatSpec { + conversion, + fill, + align, + sign, + alternate_form, + width, + grouping_option, + precision, + format_type, + }) + } + + fn compute_fill_string(fill_char: char, fill_chars_needed: i32) -> String { + (0..fill_chars_needed) + .map(|_| fill_char) + .collect::() + } + + fn add_magnitude_separators_for_char( + magnitude_str: String, + inter: i32, + sep: char, + disp_digit_cnt: i32, + ) -> String { + // Don't add separators to the floating decimal point of numbers + let mut parts = magnitude_str.splitn(2, '.'); + let magnitude_int_str = parts.next().unwrap().to_string(); + let dec_digit_cnt = magnitude_str.len() as i32 - magnitude_int_str.len() as i32; + let int_digit_cnt = disp_digit_cnt - dec_digit_cnt; + let mut result = FormatSpec::separate_integer(magnitude_int_str, inter, sep, int_digit_cnt); + if let Some(part) = parts.next() { + result.push_str(&format!(".{part}")) + } + result + } + + fn separate_integer( + magnitude_str: String, + inter: i32, + sep: char, + disp_digit_cnt: i32, + ) -> String { + let magnitude_len = magnitude_str.len() as i32; + let offset = (disp_digit_cnt % (inter + 1) == 0) as i32; + let disp_digit_cnt = disp_digit_cnt + offset; + let pad_cnt = disp_digit_cnt - magnitude_len; + let sep_cnt = disp_digit_cnt / (inter + 1); + let diff = pad_cnt - sep_cnt; + if pad_cnt > 0 && diff > 0 { + // separate with 0 padding + let padding = "0".repeat(diff as usize); + let padded_num = format!("{padding}{magnitude_str}"); + FormatSpec::insert_separator(padded_num, inter, sep, sep_cnt) + } else { + // separate without padding + let sep_cnt = (magnitude_len - 1) / inter; + FormatSpec::insert_separator(magnitude_str, inter, sep, sep_cnt) + } + } + + fn insert_separator(mut magnitude_str: String, inter: i32, sep: char, sep_cnt: i32) -> String { + let magnitude_len = magnitude_str.len() as i32; + for i in 1..sep_cnt + 1 { + magnitude_str.insert((magnitude_len - inter * i) as usize, sep); + } + magnitude_str + } + + fn validate_format(&self, default_format_type: FormatType) -> Result<(), FormatSpecError> { + let format_type = self.format_type.as_ref().unwrap_or(&default_format_type); + match (&self.grouping_option, format_type) { + ( + Some(FormatGrouping::Comma), + FormatType::String + | FormatType::Character + | FormatType::Binary + | FormatType::Octal + | FormatType::Hex(_) + | FormatType::Number(_), + ) => { + let ch = char::from(format_type); + Err(FormatSpecError::UnspecifiedFormat(',', ch)) + } + ( + Some(FormatGrouping::Underscore), + FormatType::String | FormatType::Character | FormatType::Number(_), + ) => { + let ch = char::from(format_type); + Err(FormatSpecError::UnspecifiedFormat('_', ch)) + } + _ => Ok(()), + } + } + + fn get_separator_interval(&self) -> usize { + match self.format_type { + Some(FormatType::Binary | FormatType::Octal | FormatType::Hex(_)) => 4, + Some(FormatType::Decimal | FormatType::Number(_) | FormatType::FixedPoint(_)) => 3, + None => 3, + _ => panic!("Separators only valid for numbers!"), + } + } + + fn add_magnitude_separators(&self, magnitude_str: String, prefix: &str) -> String { + match &self.grouping_option { + Some(fg) => { + let sep = match fg { + FormatGrouping::Comma => ',', + FormatGrouping::Underscore => '_', + }; + let inter = self.get_separator_interval().try_into().unwrap(); + let magnitude_len = magnitude_str.len(); + let width = self.width.unwrap_or(magnitude_len) as i32 - prefix.len() as i32; + let disp_digit_cnt = cmp::max(width, magnitude_len as i32); + FormatSpec::add_magnitude_separators_for_char( + magnitude_str, + inter, + sep, + disp_digit_cnt, + ) + } + None => magnitude_str, + } + } + + pub fn format_bool(&self, input: bool) -> Result { + let x = u8::from(input); + match &self.format_type { + Some( + FormatType::Binary + | FormatType::Decimal + | FormatType::Octal + | FormatType::Number(Case::Lower) + | FormatType::Hex(_) + | FormatType::GeneralFormat(_) + | FormatType::Character, + ) => self.format_int(&BigInt::from_u8(x).unwrap()), + Some(FormatType::Exponent(_) | FormatType::FixedPoint(_) | FormatType::Percentage) => { + self.format_float(x as f64) + } + None => { + let first_letter = (input.to_string().as_bytes()[0] as char).to_uppercase(); + Ok(first_letter.collect::() + &input.to_string()[1..]) + } + _ => Err(FormatSpecError::InvalidFormatSpecifier), + } + } + + pub fn format_float(&self, num: f64) -> Result { + self.validate_format(FormatType::FixedPoint(Case::Lower))?; + let precision = self.precision.unwrap_or(6); + let magnitude = num.abs(); + let raw_magnitude_str: Result = match &self.format_type { + Some(FormatType::FixedPoint(case)) => Ok(float::format_fixed( + precision, + magnitude, + *case, + self.alternate_form, + )), + Some(FormatType::Decimal) + | Some(FormatType::Binary) + | Some(FormatType::Octal) + | Some(FormatType::Hex(_)) + | Some(FormatType::String) + | Some(FormatType::Character) + | Some(FormatType::Number(Case::Upper)) => { + let ch = char::from(self.format_type.as_ref().unwrap()); + Err(FormatSpecError::UnknownFormatCode(ch, "float")) + } + Some(FormatType::GeneralFormat(case)) | Some(FormatType::Number(case)) => { + let precision = if precision == 0 { 1 } else { precision }; + Ok(float::format_general( + precision, + magnitude, + *case, + self.alternate_form, + false, + )) + } + Some(FormatType::Exponent(case)) => Ok(float::format_exponent( + precision, + magnitude, + *case, + self.alternate_form, + )), + Some(FormatType::Percentage) => match magnitude { + magnitude if magnitude.is_nan() => Ok("nan%".to_owned()), + magnitude if magnitude.is_infinite() => Ok("inf%".to_owned()), + _ => { + let result = format!("{:.*}", precision, magnitude * 100.0); + let point = float::decimal_point_or_empty(precision, self.alternate_form); + Ok(format!("{result}{point}%")) + } + }, + None => match magnitude { + magnitude if magnitude.is_nan() => Ok("nan".to_owned()), + magnitude if magnitude.is_infinite() => Ok("inf".to_owned()), + _ => match self.precision { + Some(precision) => Ok(float::format_general( + precision, + magnitude, + Case::Lower, + self.alternate_form, + true, + )), + None => Ok(float::to_string(magnitude)), + }, + }, + }; + let format_sign = self.sign.unwrap_or(FormatSign::Minus); + let sign_str = if num.is_sign_negative() && !num.is_nan() { + "-" + } else { + match format_sign { + FormatSign::Plus => "+", + FormatSign::Minus => "", + FormatSign::MinusOrSpace => " ", + } + }; + let magnitude_str = self.add_magnitude_separators(raw_magnitude_str?, sign_str); + self.format_sign_and_align(&AsciiStr::new(&magnitude_str), sign_str, FormatAlign::Right) + } + + #[inline] + fn format_int_radix(&self, magnitude: BigInt, radix: u32) -> Result { + match self.precision { + Some(_) => Err(FormatSpecError::PrecisionNotAllowed), + None => Ok(magnitude.to_str_radix(radix)), + } + } + + pub fn format_int(&self, num: &BigInt) -> Result { + self.validate_format(FormatType::Decimal)?; + let magnitude = num.abs(); + let prefix = if self.alternate_form { + match self.format_type { + Some(FormatType::Binary) => "0b", + Some(FormatType::Octal) => "0o", + Some(FormatType::Hex(Case::Lower)) => "0x", + Some(FormatType::Hex(Case::Upper)) => "0X", + _ => "", + } + } else { + "" + }; + let raw_magnitude_str = match self.format_type { + Some(FormatType::Binary) => self.format_int_radix(magnitude, 2), + Some(FormatType::Decimal) => self.format_int_radix(magnitude, 10), + Some(FormatType::Octal) => self.format_int_radix(magnitude, 8), + Some(FormatType::Hex(Case::Lower)) => self.format_int_radix(magnitude, 16), + Some(FormatType::Hex(Case::Upper)) => match self.precision { + Some(_) => Err(FormatSpecError::PrecisionNotAllowed), + None => { + let mut result = magnitude.to_str_radix(16); + result.make_ascii_uppercase(); + Ok(result) + } + }, + Some(FormatType::Number(Case::Lower)) => self.format_int_radix(magnitude, 10), + Some(FormatType::Number(Case::Upper)) => { + Err(FormatSpecError::UnknownFormatCode('N', "int")) + } + Some(FormatType::String) => Err(FormatSpecError::UnknownFormatCode('s', "int")), + Some(FormatType::Character) => match (self.sign, self.alternate_form) { + (Some(_), _) => Err(FormatSpecError::NotAllowed("Sign")), + (_, true) => Err(FormatSpecError::NotAllowed("Alternate form (#)")), + (_, _) => match num.to_u32() { + Some(n) if n <= 0x10ffff => Ok(std::char::from_u32(n).unwrap().to_string()), + Some(_) | None => Err(FormatSpecError::CodeNotInRange), + }, + }, + Some(FormatType::GeneralFormat(_)) + | Some(FormatType::FixedPoint(_)) + | Some(FormatType::Exponent(_)) + | Some(FormatType::Percentage) => match num.to_f64() { + Some(float) => return self.format_float(float), + _ => Err(FormatSpecError::UnableToConvert), + }, + None => self.format_int_radix(magnitude, 10), + }?; + let format_sign = self.sign.unwrap_or(FormatSign::Minus); + let sign_str = match num.sign() { + Sign::Minus => "-", + _ => match format_sign { + FormatSign::Plus => "+", + FormatSign::Minus => "", + FormatSign::MinusOrSpace => " ", + }, + }; + let sign_prefix = format!("{sign_str}{prefix}"); + let magnitude_str = self.add_magnitude_separators(raw_magnitude_str, &sign_prefix); + self.format_sign_and_align( + &AsciiStr::new(&magnitude_str), + &sign_prefix, + FormatAlign::Right, + ) + } + + pub fn format_string(&self, s: &T) -> Result + where + T: CharLen + Deref, + { + self.validate_format(FormatType::String)?; + match self.format_type { + Some(FormatType::String) | None => self + .format_sign_and_align(s, "", FormatAlign::Left) + .map(|mut value| { + if let Some(precision) = self.precision { + value.truncate(precision); + } + value + }), + _ => { + let ch = char::from(self.format_type.as_ref().unwrap()); + Err(FormatSpecError::UnknownFormatCode(ch, "str")) + } + } + } + + fn format_sign_and_align( + &self, + magnitude_str: &T, + sign_str: &str, + default_align: FormatAlign, + ) -> Result + where + T: CharLen + Deref, + { + let align = self.align.unwrap_or(default_align); + + let num_chars = magnitude_str.char_len(); + let fill_char = self.fill.unwrap_or(' '); + let fill_chars_needed: i32 = self.width.map_or(0, |w| { + cmp::max(0, (w as i32) - (num_chars as i32) - (sign_str.len() as i32)) + }); + + let magnitude_str = magnitude_str.deref(); + Ok(match align { + FormatAlign::Left => format!( + "{}{}{}", + sign_str, + magnitude_str, + FormatSpec::compute_fill_string(fill_char, fill_chars_needed) + ), + FormatAlign::Right => format!( + "{}{}{}", + FormatSpec::compute_fill_string(fill_char, fill_chars_needed), + sign_str, + magnitude_str + ), + FormatAlign::AfterSign => format!( + "{}{}{}", + sign_str, + FormatSpec::compute_fill_string(fill_char, fill_chars_needed), + magnitude_str + ), + FormatAlign::Center => { + let left_fill_chars_needed = fill_chars_needed / 2; + let right_fill_chars_needed = fill_chars_needed - left_fill_chars_needed; + let left_fill_string = + FormatSpec::compute_fill_string(fill_char, left_fill_chars_needed); + let right_fill_string = + FormatSpec::compute_fill_string(fill_char, right_fill_chars_needed); + format!("{left_fill_string}{sign_str}{magnitude_str}{right_fill_string}") + } + }) + } +} + +pub trait CharLen { + /// Returns the number of characters in the text + fn char_len(&self) -> usize; +} + +struct AsciiStr<'a> { + inner: &'a str, +} + +impl<'a> AsciiStr<'a> { + fn new(inner: &'a str) -> Self { + Self { inner } + } +} + +impl CharLen for AsciiStr<'_> { + fn char_len(&self) -> usize { + self.inner.len() + } +} + +impl Deref for AsciiStr<'_> { + type Target = str; + fn deref(&self) -> &Self::Target { + self.inner + } +} + +#[derive(Debug, PartialEq)] +pub enum FormatSpecError { + DecimalDigitsTooMany, + PrecisionTooBig, + InvalidFormatSpecifier, + UnspecifiedFormat(char, char), + UnknownFormatCode(char, &'static str), + PrecisionNotAllowed, + NotAllowed(&'static str), + UnableToConvert, + CodeNotInRange, + NotImplemented(char, &'static str), +} + +#[derive(Debug, PartialEq)] +pub enum FormatParseError { + UnmatchedBracket, + MissingStartBracket, + UnescapedStartBracketInLiteral, + InvalidFormatSpecifier, + UnknownConversion, + EmptyAttribute, + MissingRightBracket, + InvalidCharacterAfterRightBracket, +} + +impl FromStr for FormatSpec { + type Err = FormatSpecError; + fn from_str(s: &str) -> Result { + FormatSpec::parse(s) + } +} + +#[derive(Debug, PartialEq)] +pub enum FieldNamePart { + Attribute(String), + Index(usize), + StringIndex(String), +} + +impl FieldNamePart { + fn parse_part( + chars: &mut impl PeekingNext, + ) -> Result, FormatParseError> { + chars + .next() + .map(|ch| match ch { + '.' => { + let mut attribute = String::new(); + for ch in chars.peeking_take_while(|ch| *ch != '.' && *ch != '[') { + attribute.push(ch); + } + if attribute.is_empty() { + Err(FormatParseError::EmptyAttribute) + } else { + Ok(FieldNamePart::Attribute(attribute)) + } + } + '[' => { + let mut index = String::new(); + for ch in chars { + if ch == ']' { + return if index.is_empty() { + Err(FormatParseError::EmptyAttribute) + } else if let Ok(index) = index.parse::() { + Ok(FieldNamePart::Index(index)) + } else { + Ok(FieldNamePart::StringIndex(index)) + }; + } + index.push(ch); + } + Err(FormatParseError::MissingRightBracket) + } + _ => Err(FormatParseError::InvalidCharacterAfterRightBracket), + }) + .transpose() + } +} + +#[derive(Debug, PartialEq)] +pub enum FieldType { + Auto, + Index(usize), + Keyword(String), +} + +#[derive(Debug, PartialEq)] +pub struct FieldName { + pub field_type: FieldType, + pub parts: Vec, +} + +impl FieldName { + pub fn parse(text: &str) -> Result { + let mut chars = text.chars().peekable(); + let mut first = String::new(); + for ch in chars.peeking_take_while(|ch| *ch != '.' && *ch != '[') { + first.push(ch); + } + + let field_type = if first.is_empty() { + FieldType::Auto + } else if let Ok(index) = first.parse::() { + FieldType::Index(index) + } else { + FieldType::Keyword(first) + }; + + let mut parts = Vec::new(); + while let Some(part) = FieldNamePart::parse_part(&mut chars)? { + parts.push(part) + } + + Ok(FieldName { field_type, parts }) + } +} + +#[derive(Debug, PartialEq)] +pub enum FormatPart { + Field { + field_name: String, + conversion_spec: Option, + format_spec: String, + }, + Literal(String), +} + +#[derive(Debug, PartialEq)] +pub struct FormatString { + pub format_parts: Vec, +} + +impl FormatString { + fn parse_literal_single(text: &str) -> Result<(char, &str), FormatParseError> { + let mut chars = text.chars(); + // This should never be called with an empty str + let first_char = chars.next().unwrap(); + // isn't this detectable only with bytes operation? + if first_char == '{' || first_char == '}' { + let maybe_next_char = chars.next(); + // if we see a bracket, it has to be escaped by doubling up to be in a literal + return if maybe_next_char.is_none() || maybe_next_char.unwrap() != first_char { + Err(FormatParseError::UnescapedStartBracketInLiteral) + } else { + Ok((first_char, chars.as_str())) + }; + } + Ok((first_char, chars.as_str())) + } + + fn parse_literal(text: &str) -> Result<(FormatPart, &str), FormatParseError> { + let mut cur_text = text; + let mut result_string = String::new(); + while !cur_text.is_empty() { + match FormatString::parse_literal_single(cur_text) { + Ok((next_char, remaining)) => { + result_string.push(next_char); + cur_text = remaining; + } + Err(err) => { + return if !result_string.is_empty() { + Ok((FormatPart::Literal(result_string), cur_text)) + } else { + Err(err) + }; + } + } + } + Ok((FormatPart::Literal(result_string), "")) + } + + fn parse_part_in_brackets(text: &str) -> Result { + let parts: Vec<&str> = text.splitn(2, ':').collect(); + // before the comma is a keyword or arg index, after the comma is maybe a spec. + let arg_part = parts[0]; + + let format_spec = if parts.len() > 1 { + parts[1].to_owned() + } else { + String::new() + }; + + // On parts[0] can still be the conversion (!r, !s, !a) + let parts: Vec<&str> = arg_part.splitn(2, '!').collect(); + // before the bang is a keyword or arg index, after the comma is maybe a conversion spec. + let arg_part = parts[0]; + + let conversion_spec = parts + .get(1) + .map(|conversion| { + // conversions are only every one character + conversion + .chars() + .exactly_one() + .map_err(|_| FormatParseError::UnknownConversion) + }) + .transpose()?; + + Ok(FormatPart::Field { + field_name: arg_part.to_owned(), + conversion_spec, + format_spec, + }) + } + + fn parse_spec(text: &str) -> Result<(FormatPart, &str), FormatParseError> { + let mut nested = false; + let mut end_bracket_pos = None; + let mut left = String::new(); + + // There may be one layer nesting brackets in spec + for (idx, c) in text.char_indices() { + if idx == 0 { + if c != '{' { + return Err(FormatParseError::MissingStartBracket); + } + } else if c == '{' { + if nested { + return Err(FormatParseError::InvalidFormatSpecifier); + } else { + nested = true; + left.push(c); + continue; + } + } else if c == '}' { + if nested { + nested = false; + left.push(c); + continue; + } else { + end_bracket_pos = Some(idx); + break; + } + } else { + left.push(c); + } + } + if let Some(pos) = end_bracket_pos { + let (_, right) = text.split_at(pos); + let format_part = FormatString::parse_part_in_brackets(&left)?; + Ok((format_part, &right[1..])) + } else { + Err(FormatParseError::UnmatchedBracket) + } + } +} + +pub trait FromTemplate<'a>: Sized { + type Err; + fn from_str(s: &'a str) -> Result; +} + +impl<'a> FromTemplate<'a> for FormatString { + type Err = FormatParseError; + + fn from_str(text: &'a str) -> Result { + let mut cur_text: &str = text; + let mut parts: Vec = Vec::new(); + while !cur_text.is_empty() { + // Try to parse both literals and bracketed format parts until we + // run out of text + cur_text = FormatString::parse_literal(cur_text) + .or_else(|_| FormatString::parse_spec(cur_text)) + .map(|(part, new_text)| { + parts.push(part); + new_text + })?; + } + Ok(FormatString { + format_parts: parts, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_fill_and_align() { + assert_eq!( + parse_fill_and_align(" <"), + (Some(' '), Some(FormatAlign::Left), "") + ); + assert_eq!( + parse_fill_and_align(" <22"), + (Some(' '), Some(FormatAlign::Left), "22") + ); + assert_eq!( + parse_fill_and_align("<22"), + (None, Some(FormatAlign::Left), "22") + ); + assert_eq!( + parse_fill_and_align(" ^^"), + (Some(' '), Some(FormatAlign::Center), "^") + ); + assert_eq!( + parse_fill_and_align("==="), + (Some('='), Some(FormatAlign::AfterSign), "=") + ); + } + + #[test] + fn test_width_only() { + let expected = Ok(FormatSpec { + conversion: None, + fill: None, + align: None, + sign: None, + alternate_form: false, + width: Some(33), + grouping_option: None, + precision: None, + format_type: None, + }); + assert_eq!(FormatSpec::parse("33"), expected); + } + + #[test] + fn test_fill_and_width() { + let expected = Ok(FormatSpec { + conversion: None, + fill: Some('<'), + align: Some(FormatAlign::Right), + sign: None, + alternate_form: false, + width: Some(33), + grouping_option: None, + precision: None, + format_type: None, + }); + assert_eq!(FormatSpec::parse("<>33"), expected); + } + + #[test] + fn test_all() { + let expected = Ok(FormatSpec { + conversion: None, + fill: Some('<'), + align: Some(FormatAlign::Right), + sign: Some(FormatSign::Minus), + alternate_form: true, + width: Some(23), + grouping_option: Some(FormatGrouping::Comma), + precision: Some(11), + format_type: Some(FormatType::Binary), + }); + assert_eq!(FormatSpec::parse("<>-#23,.11b"), expected); + } + + fn format_bool(text: &str, value: bool) -> Result { + FormatSpec::parse(text).and_then(|spec| spec.format_bool(value)) + } + + #[test] + fn test_format_bool() { + assert_eq!(format_bool("b", true), Ok("1".to_owned())); + assert_eq!(format_bool("b", false), Ok("0".to_owned())); + assert_eq!(format_bool("d", true), Ok("1".to_owned())); + assert_eq!(format_bool("d", false), Ok("0".to_owned())); + assert_eq!(format_bool("o", true), Ok("1".to_owned())); + assert_eq!(format_bool("o", false), Ok("0".to_owned())); + assert_eq!(format_bool("n", true), Ok("1".to_owned())); + assert_eq!(format_bool("n", false), Ok("0".to_owned())); + assert_eq!(format_bool("x", true), Ok("1".to_owned())); + assert_eq!(format_bool("x", false), Ok("0".to_owned())); + assert_eq!(format_bool("X", true), Ok("1".to_owned())); + assert_eq!(format_bool("X", false), Ok("0".to_owned())); + assert_eq!(format_bool("g", true), Ok("1".to_owned())); + assert_eq!(format_bool("g", false), Ok("0".to_owned())); + assert_eq!(format_bool("G", true), Ok("1".to_owned())); + assert_eq!(format_bool("G", false), Ok("0".to_owned())); + assert_eq!(format_bool("c", true), Ok("\x01".to_owned())); + assert_eq!(format_bool("c", false), Ok("\x00".to_owned())); + assert_eq!(format_bool("e", true), Ok("1.000000e+00".to_owned())); + assert_eq!(format_bool("e", false), Ok("0.000000e+00".to_owned())); + assert_eq!(format_bool("E", true), Ok("1.000000E+00".to_owned())); + assert_eq!(format_bool("E", false), Ok("0.000000E+00".to_owned())); + assert_eq!(format_bool("f", true), Ok("1.000000".to_owned())); + assert_eq!(format_bool("f", false), Ok("0.000000".to_owned())); + assert_eq!(format_bool("F", true), Ok("1.000000".to_owned())); + assert_eq!(format_bool("F", false), Ok("0.000000".to_owned())); + assert_eq!(format_bool("%", true), Ok("100.000000%".to_owned())); + assert_eq!(format_bool("%", false), Ok("0.000000%".to_owned())); + } + + #[test] + fn test_format_int() { + assert_eq!( + FormatSpec::parse("d") + .unwrap() + .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), + Ok("16".to_owned()) + ); + assert_eq!( + FormatSpec::parse("x") + .unwrap() + .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), + Ok("10".to_owned()) + ); + assert_eq!( + FormatSpec::parse("b") + .unwrap() + .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), + Ok("10000".to_owned()) + ); + assert_eq!( + FormatSpec::parse("o") + .unwrap() + .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), + Ok("20".to_owned()) + ); + assert_eq!( + FormatSpec::parse("+d") + .unwrap() + .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), + Ok("+16".to_owned()) + ); + assert_eq!( + FormatSpec::parse("^ 5d") + .unwrap() + .format_int(&BigInt::from_bytes_be(Sign::Minus, b"\x10")), + Ok(" -16 ".to_owned()) + ); + assert_eq!( + FormatSpec::parse("0>+#10x") + .unwrap() + .format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")), + Ok("00000+0x10".to_owned()) + ); + } + + #[test] + fn test_format_int_sep() { + let spec = FormatSpec::parse(",").expect(""); + assert_eq!(spec.grouping_option, Some(FormatGrouping::Comma)); + assert_eq!( + spec.format_int(&BigInt::from_str("1234567890123456789012345678").unwrap()), + Ok("1,234,567,890,123,456,789,012,345,678".to_owned()) + ); + } + + #[test] + fn test_format_parse() { + let expected = Ok(FormatString { + format_parts: vec![ + FormatPart::Literal("abcd".to_owned()), + FormatPart::Field { + field_name: "1".to_owned(), + conversion_spec: None, + format_spec: String::new(), + }, + FormatPart::Literal(":".to_owned()), + FormatPart::Field { + field_name: "key".to_owned(), + conversion_spec: None, + format_spec: String::new(), + }, + ], + }); + + assert_eq!(FormatString::from_str("abcd{1}:{key}"), expected); + } + + #[test] + fn test_format_parse_multi_byte_char() { + assert!(FormatString::from_str("{a:%ЫйЯЧ}").is_ok()); + } + + #[test] + fn test_format_parse_fail() { + assert_eq!( + FormatString::from_str("{s"), + Err(FormatParseError::UnmatchedBracket) + ); + } + + #[test] + fn test_format_parse_escape() { + let expected = Ok(FormatString { + format_parts: vec![ + FormatPart::Literal("{".to_owned()), + FormatPart::Field { + field_name: "key".to_owned(), + conversion_spec: None, + format_spec: String::new(), + }, + FormatPart::Literal("}ddfe".to_owned()), + ], + }); + + assert_eq!(FormatString::from_str("{{{key}}}ddfe"), expected); + } + + #[test] + fn test_format_invalid_specification() { + assert_eq!( + FormatSpec::parse("%3"), + Err(FormatSpecError::InvalidFormatSpecifier) + ); + assert_eq!( + FormatSpec::parse(".2fa"), + Err(FormatSpecError::InvalidFormatSpecifier) + ); + assert_eq!( + FormatSpec::parse("ds"), + Err(FormatSpecError::InvalidFormatSpecifier) + ); + assert_eq!( + FormatSpec::parse("x+"), + Err(FormatSpecError::InvalidFormatSpecifier) + ); + assert_eq!( + FormatSpec::parse("b4"), + Err(FormatSpecError::InvalidFormatSpecifier) + ); + assert_eq!( + FormatSpec::parse("o!"), + Err(FormatSpecError::InvalidFormatSpecifier) + ); + assert_eq!( + FormatSpec::parse("d "), + Err(FormatSpecError::InvalidFormatSpecifier) + ); + } + + #[test] + fn test_parse_field_name() { + assert_eq!( + FieldName::parse(""), + Ok(FieldName { + field_type: FieldType::Auto, + parts: Vec::new(), + }) + ); + assert_eq!( + FieldName::parse("0"), + Ok(FieldName { + field_type: FieldType::Index(0), + parts: Vec::new(), + }) + ); + assert_eq!( + FieldName::parse("key"), + Ok(FieldName { + field_type: FieldType::Keyword("key".to_owned()), + parts: Vec::new(), + }) + ); + assert_eq!( + FieldName::parse("key.attr[0][string]"), + Ok(FieldName { + field_type: FieldType::Keyword("key".to_owned()), + parts: vec![ + FieldNamePart::Attribute("attr".to_owned()), + FieldNamePart::Index(0), + FieldNamePart::StringIndex("string".to_owned()) + ], + }) + ); + assert_eq!( + FieldName::parse("key.."), + Err(FormatParseError::EmptyAttribute) + ); + assert_eq!( + FieldName::parse("key[]"), + Err(FormatParseError::EmptyAttribute) + ); + assert_eq!( + FieldName::parse("key["), + Err(FormatParseError::MissingRightBracket) + ); + assert_eq!( + FieldName::parse("key[0]after"), + Err(FormatParseError::InvalidCharacterAfterRightBracket) + ); + } } diff --git a/literal/src/lib.rs b/literal/src/lib.rs index 9b962057..7c9025b4 100644 --- a/literal/src/lib.rs +++ b/literal/src/lib.rs @@ -1,4 +1,11 @@ +pub mod cformat; pub mod char; pub mod escape; pub mod float; pub mod format; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Case { + Lower, + Upper, +} diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_empty.snap b/parser/src/snapshots/rustpython_parser__parser__tests__parse_empty.snap deleted file mode 100644 index 17be8fe7..00000000 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_empty.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: compiler/parser/src/parser.rs -expression: parse_ast ---- -[] diff --git a/ruff_python_ast/Cargo.toml b/ruff_python_ast/Cargo.toml new file mode 100644 index 00000000..b7235f9c --- /dev/null +++ b/ruff_python_ast/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "ruff_python_ast" +version = "0.2.0" +description = "AST definitions for Ruff" +authors = ["Charlie Marsh "] +edition = "2021" +repository = "https://github.com/astral-sh/ruff" +license = "MIT" + +[dependencies] +ruff_text_size = { workspace = true } + +is-macro = { workspace = true } +num-bigint = { workspace = true } +static_assertions = { workspace = true } diff --git a/ast/src/lib.rs b/ruff_python_ast/src/lib.rs similarity index 56% rename from ast/src/lib.rs rename to ruff_python_ast/src/lib.rs index cbb12ce2..31a45fcf 100644 --- a/ast/src/lib.rs +++ b/ruff_python_ast/src/lib.rs @@ -1,7 +1,7 @@ //! Python AST node definitions and utilities. //! //! AST nodes are very similary defined like [Python AST](https://docs.python.org/3/library/ast.html). -//! But a few exceptions exist due to parser optimization. +//! But a few exceptions exist due to ruff_python_parser optimization. //! They can be transformed to matching Python-styled AST in reasonable cost. //! //! [PythonArguments] is replaced by [Arguments]. The new [Arguments] type representation uses a new type @@ -15,17 +15,34 @@ //! [ExceptHandler] refers `excepthandler` //! -mod builtin; -mod generic; -mod impls; -mod ranged; +mod nodes; -pub use builtin::*; -pub use generic::*; -pub use ranged::Ranged; -pub use rustpython_parser_core::{text_size, ConversionFlag}; +pub use nodes::*; +use ruff_text_size::{TextRange, TextSize}; -pub trait Node { - const NAME: &'static str; - const FIELD_NAMES: &'static [&'static str]; +pub trait Ranged { + fn range(&self) -> TextRange; + + fn start(&self) -> TextSize { + self.range().start() + } + + fn end(&self) -> TextSize { + self.range().end() + } +} + +impl Ranged for TextRange { + fn range(&self) -> TextRange { + *self + } +} + +impl Ranged for &T +where + T: Ranged, +{ + fn range(&self) -> TextRange { + T::range(self) + } } diff --git a/ast/src/generic.rs b/ruff_python_ast/src/nodes.rs similarity index 63% rename from ast/src/generic.rs rename to ruff_python_ast/src/nodes.rs index df9575da..ccb4463e 100644 --- a/ast/src/generic.rs +++ b/ruff_python_ast/src/nodes.rs @@ -1,158 +1,10 @@ #![allow(clippy::derive_partial_eq_without_eq)] -use crate::text_size::{TextRange, TextSize}; -pub(crate) use crate::{builtin::*, ConversionFlag, Node}; -use std::fmt::{self, Debug}; -// This file was originally generated from asdl by a python script, but we now edit it manually - -#[derive(Clone, Debug, PartialEq, is_macro::Is)] -pub enum Ast { - #[is(name = "module")] - Mod(Mod), - Stmt(Stmt), - Expr(Expr), - ExprContext(ExprContext), - BoolOp(BoolOp), - Operator(Operator), - UnaryOp(UnaryOp), - CmpOp(CmpOp), - Comprehension(Comprehension), - ExceptHandler(ExceptHandler), - Arguments(Arguments), - Arg(Arg), - Keyword(Keyword), - Alias(Alias), - WithItem(WithItem), - MatchCase(MatchCase), - Pattern(Pattern), - TypeIgnore(TypeIgnore), - TypeParam(TypeParam), - Decorator(Decorator), -} -impl Node for Ast { - const NAME: &'static str = "AST"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} - -impl From for Ast { - fn from(node: Mod) -> Self { - Ast::Mod(node) - } -} - -impl From for Ast { - fn from(node: Stmt) -> Self { - Ast::Stmt(node) - } -} - -impl From for Ast { - fn from(node: Expr) -> Self { - Ast::Expr(node) - } -} - -impl From for Ast { - fn from(node: ExprContext) -> Self { - Ast::ExprContext(node) - } -} - -impl From for Ast { - fn from(node: BoolOp) -> Self { - Ast::BoolOp(node) - } -} - -impl From for Ast { - fn from(node: Operator) -> Self { - Ast::Operator(node) - } -} - -impl From for Ast { - fn from(node: UnaryOp) -> Self { - Ast::UnaryOp(node) - } -} - -impl From for Ast { - fn from(node: CmpOp) -> Self { - Ast::CmpOp(node) - } -} - -impl From for Ast { - fn from(node: Comprehension) -> Self { - Ast::Comprehension(node) - } -} - -impl From for Ast { - fn from(node: ExceptHandler) -> Self { - Ast::ExceptHandler(node) - } -} - -impl From for Ast { - fn from(node: Arguments) -> Self { - Ast::Arguments(node) - } -} - -impl From for Ast { - fn from(node: Arg) -> Self { - Ast::Arg(node) - } -} - -impl From for Ast { - fn from(node: Keyword) -> Self { - Ast::Keyword(node) - } -} - -impl From for Ast { - fn from(node: Alias) -> Self { - Ast::Alias(node) - } -} - -impl From for Ast { - fn from(node: WithItem) -> Self { - Ast::WithItem(node) - } -} - -impl From for Ast { - fn from(node: MatchCase) -> Self { - Ast::MatchCase(node) - } -} - -impl From for Ast { - fn from(node: Pattern) -> Self { - Ast::Pattern(node) - } -} - -impl From for Ast { - fn from(node: TypeIgnore) -> Self { - Ast::TypeIgnore(node) - } -} - -impl From for Ast { - fn from(node: TypeParam) -> Self { - Ast::TypeParam(node) - } -} - -impl From for Ast { - fn from(node: Decorator) -> Self { - Ast::Decorator(node) - } -} +use crate::Ranged; +use num_bigint::BigInt; +use ruff_text_size::{TextRange, TextSize}; +use std::fmt; +use std::fmt::Debug; /// See also [mod](https://docs.python.org/3/library/ast.html#ast.mod) #[derive(Clone, Debug, PartialEq, is_macro::Is)] @@ -171,20 +23,11 @@ pub struct ModModule { pub type_ignores: Vec, } -impl Node for ModModule { - const NAME: &'static str = "Module"; - const FIELD_NAMES: &'static [&'static str] = &["body", "type_ignores"]; -} impl From for Mod { fn from(payload: ModModule) -> Self { Mod::Module(payload) } } -impl From for Ast { - fn from(payload: ModModule) -> Self { - Mod::from(payload).into() - } -} /// See also [Interactive](https://docs.python.org/3/library/ast.html#ast.Interactive) #[derive(Clone, Debug, PartialEq)] @@ -193,20 +36,11 @@ pub struct ModInteractive { pub body: Vec, } -impl Node for ModInteractive { - const NAME: &'static str = "Interactive"; - const FIELD_NAMES: &'static [&'static str] = &["body"]; -} impl From for Mod { fn from(payload: ModInteractive) -> Self { Mod::Interactive(payload) } } -impl From for Ast { - fn from(payload: ModInteractive) -> Self { - Mod::from(payload).into() - } -} /// See also [Expression](https://docs.python.org/3/library/ast.html#ast.Expression) #[derive(Clone, Debug, PartialEq)] @@ -215,20 +49,11 @@ pub struct ModExpression { pub body: Box, } -impl Node for ModExpression { - const NAME: &'static str = "Expression"; - const FIELD_NAMES: &'static [&'static str] = &["body"]; -} impl From for Mod { fn from(payload: ModExpression) -> Self { Mod::Expression(payload) } } -impl From for Ast { - fn from(payload: ModExpression) -> Self { - Mod::from(payload).into() - } -} /// See also [FunctionType](https://docs.python.org/3/library/ast.html#ast.FunctionType) #[derive(Clone, Debug, PartialEq)] @@ -238,25 +63,11 @@ pub struct ModFunctionType { pub returns: Box, } -impl Node for ModFunctionType { - const NAME: &'static str = "FunctionType"; - const FIELD_NAMES: &'static [&'static str] = &["argtypes", "returns"]; -} impl From for Mod { fn from(payload: ModFunctionType) -> Self { Mod::FunctionType(payload) } } -impl From for Ast { - fn from(payload: ModFunctionType) -> Self { - Mod::from(payload).into() - } -} - -impl Node for Mod { - const NAME: &'static str = "mod"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} /// See also [stmt](https://docs.python.org/3/library/ast.html#ast.stmt) #[derive(Clone, Debug, PartialEq, is_macro::Is)] @@ -330,20 +141,11 @@ pub struct StmtLineMagic { pub value: String, } -impl Node for StmtLineMagic { - const NAME: &'static str = "LineMagic"; - const FIELD_NAMES: &'static [&'static str] = &["kind", "value"]; -} impl From for Stmt { fn from(payload: StmtLineMagic) -> Self { Stmt::LineMagic(payload) } } -impl From for Ast { - fn from(payload: StmtLineMagic) -> Self { - Stmt::from(payload).into() - } -} /// See also [FunctionDef](https://docs.python.org/3/library/ast.html#ast.FunctionDef) #[derive(Clone, Debug, PartialEq)] @@ -358,28 +160,11 @@ pub struct StmtFunctionDef { pub type_comment: Option, } -impl Node for StmtFunctionDef { - const NAME: &'static str = "FunctionDef"; - const FIELD_NAMES: &'static [&'static str] = &[ - "name", - "args", - "body", - "decorator_list", - "returns", - "type_params", - "type_comment", - ]; -} impl From for Stmt { fn from(payload: StmtFunctionDef) -> Self { Stmt::FunctionDef(payload) } } -impl From for Ast { - fn from(payload: StmtFunctionDef) -> Self { - Stmt::from(payload).into() - } -} /// See also [AsyncFunctionDef](https://docs.python.org/3/library/ast.html#ast.AsyncFunctionDef) #[derive(Clone, Debug, PartialEq)] @@ -394,28 +179,11 @@ pub struct StmtAsyncFunctionDef { pub type_comment: Option, } -impl Node for StmtAsyncFunctionDef { - const NAME: &'static str = "AsyncFunctionDef"; - const FIELD_NAMES: &'static [&'static str] = &[ - "name", - "args", - "body", - "decorator_list", - "returns", - "type_params", - "type_comment", - ]; -} impl From for Stmt { fn from(payload: StmtAsyncFunctionDef) -> Self { Stmt::AsyncFunctionDef(payload) } } -impl From for Ast { - fn from(payload: StmtAsyncFunctionDef) -> Self { - Stmt::from(payload).into() - } -} /// See also [ClassDef](https://docs.python.org/3/library/ast.html#ast.ClassDef) #[derive(Clone, Debug, PartialEq)] @@ -429,27 +197,11 @@ pub struct StmtClassDef { pub decorator_list: Vec, } -impl Node for StmtClassDef { - const NAME: &'static str = "ClassDef"; - const FIELD_NAMES: &'static [&'static str] = &[ - "name", - "bases", - "keywords", - "body", - "decorator_list", - "type_params", - ]; -} impl From for Stmt { fn from(payload: StmtClassDef) -> Self { Stmt::ClassDef(payload) } } -impl From for Ast { - fn from(payload: StmtClassDef) -> Self { - Stmt::from(payload).into() - } -} /// See also [Return](https://docs.python.org/3/library/ast.html#ast.Return) #[derive(Clone, Debug, PartialEq)] @@ -458,20 +210,11 @@ pub struct StmtReturn { pub value: Option>, } -impl Node for StmtReturn { - const NAME: &'static str = "Return"; - const FIELD_NAMES: &'static [&'static str] = &["value"]; -} impl From for Stmt { fn from(payload: StmtReturn) -> Self { Stmt::Return(payload) } } -impl From for Ast { - fn from(payload: StmtReturn) -> Self { - Stmt::from(payload).into() - } -} /// See also [Delete](https://docs.python.org/3/library/ast.html#ast.Delete) #[derive(Clone, Debug, PartialEq)] @@ -480,20 +223,11 @@ pub struct StmtDelete { pub targets: Vec, } -impl Node for StmtDelete { - const NAME: &'static str = "Delete"; - const FIELD_NAMES: &'static [&'static str] = &["targets"]; -} impl From for Stmt { fn from(payload: StmtDelete) -> Self { Stmt::Delete(payload) } } -impl From for Ast { - fn from(payload: StmtDelete) -> Self { - Stmt::from(payload).into() - } -} /// See also [TypeAlias](https://docs.python.org/3/library/ast.html#ast.TypeAlias) #[derive(Clone, Debug, PartialEq)] @@ -504,20 +238,11 @@ pub struct StmtTypeAlias { pub value: Box, } -impl Node for StmtTypeAlias { - const NAME: &'static str = "TypeAlias"; - const FIELD_NAMES: &'static [&'static str] = &["name", "type_params", "value"]; -} impl From for Stmt { fn from(payload: StmtTypeAlias) -> Self { Stmt::TypeAlias(payload) } } -impl From for Ast { - fn from(payload: StmtTypeAlias) -> Self { - Stmt::from(payload).into() - } -} /// See also [Assign](https://docs.python.org/3/library/ast.html#ast.Assign) #[derive(Clone, Debug, PartialEq)] @@ -528,20 +253,11 @@ pub struct StmtAssign { pub type_comment: Option, } -impl Node for StmtAssign { - const NAME: &'static str = "Assign"; - const FIELD_NAMES: &'static [&'static str] = &["targets", "value", "type_comment"]; -} impl From for Stmt { fn from(payload: StmtAssign) -> Self { Stmt::Assign(payload) } } -impl From for Ast { - fn from(payload: StmtAssign) -> Self { - Stmt::from(payload).into() - } -} /// See also [AugAssign](https://docs.python.org/3/library/ast.html#ast.AugAssign) #[derive(Clone, Debug, PartialEq)] @@ -552,20 +268,11 @@ pub struct StmtAugAssign { pub value: Box, } -impl Node for StmtAugAssign { - const NAME: &'static str = "AugAssign"; - const FIELD_NAMES: &'static [&'static str] = &["target", "op", "value"]; -} impl From for Stmt { fn from(payload: StmtAugAssign) -> Self { Stmt::AugAssign(payload) } } -impl From for Ast { - fn from(payload: StmtAugAssign) -> Self { - Stmt::from(payload).into() - } -} /// See also [AnnAssign](https://docs.python.org/3/library/ast.html#ast.AnnAssign) #[derive(Clone, Debug, PartialEq)] @@ -577,20 +284,11 @@ pub struct StmtAnnAssign { pub simple: bool, } -impl Node for StmtAnnAssign { - const NAME: &'static str = "AnnAssign"; - const FIELD_NAMES: &'static [&'static str] = &["target", "annotation", "value", "simple"]; -} impl From for Stmt { fn from(payload: StmtAnnAssign) -> Self { Stmt::AnnAssign(payload) } } -impl From for Ast { - fn from(payload: StmtAnnAssign) -> Self { - Stmt::from(payload).into() - } -} /// See also [For](https://docs.python.org/3/library/ast.html#ast.For) #[derive(Clone, Debug, PartialEq)] @@ -603,21 +301,11 @@ pub struct StmtFor { pub type_comment: Option, } -impl Node for StmtFor { - const NAME: &'static str = "For"; - const FIELD_NAMES: &'static [&'static str] = - &["target", "iter", "body", "orelse", "type_comment"]; -} impl From for Stmt { fn from(payload: StmtFor) -> Self { Stmt::For(payload) } } -impl From for Ast { - fn from(payload: StmtFor) -> Self { - Stmt::from(payload).into() - } -} /// See also [AsyncFor](https://docs.python.org/3/library/ast.html#ast.AsyncFor) #[derive(Clone, Debug, PartialEq)] @@ -630,21 +318,11 @@ pub struct StmtAsyncFor { pub type_comment: Option, } -impl Node for StmtAsyncFor { - const NAME: &'static str = "AsyncFor"; - const FIELD_NAMES: &'static [&'static str] = - &["target", "iter", "body", "orelse", "type_comment"]; -} impl From for Stmt { fn from(payload: StmtAsyncFor) -> Self { Stmt::AsyncFor(payload) } } -impl From for Ast { - fn from(payload: StmtAsyncFor) -> Self { - Stmt::from(payload).into() - } -} /// See also [While](https://docs.python.org/3/library/ast.html#ast.While) #[derive(Clone, Debug, PartialEq)] @@ -655,20 +333,11 @@ pub struct StmtWhile { pub orelse: Vec, } -impl Node for StmtWhile { - const NAME: &'static str = "While"; - const FIELD_NAMES: &'static [&'static str] = &["test", "body", "orelse"]; -} impl From for Stmt { fn from(payload: StmtWhile) -> Self { Stmt::While(payload) } } -impl From for Ast { - fn from(payload: StmtWhile) -> Self { - Stmt::from(payload).into() - } -} /// See also [If](https://docs.python.org/3/library/ast.html#ast.If) #[derive(Clone, Debug, PartialEq)] @@ -679,20 +348,11 @@ pub struct StmtIf { pub elif_else_clauses: Vec, } -impl Node for StmtIf { - const NAME: &'static str = "If"; - const FIELD_NAMES: &'static [&'static str] = &["test", "body", "elif_else_clauses"]; -} impl From for Stmt { fn from(payload: StmtIf) -> Self { Stmt::If(payload) } } -impl From for Ast { - fn from(payload: StmtIf) -> Self { - Stmt::from(payload).into() - } -} #[derive(Clone, Debug, PartialEq)] pub struct ElifElseClause { @@ -701,11 +361,6 @@ pub struct ElifElseClause { pub body: Vec, } -impl Node for ElifElseClause { - const NAME: &'static str = "ElifElse"; - const FIELD_NAMES: &'static [&'static str] = &["test", "body"]; -} - /// See also [With](https://docs.python.org/3/library/ast.html#ast.With) #[derive(Clone, Debug, PartialEq)] pub struct StmtWith { @@ -715,20 +370,11 @@ pub struct StmtWith { pub type_comment: Option, } -impl Node for StmtWith { - const NAME: &'static str = "With"; - const FIELD_NAMES: &'static [&'static str] = &["items", "body", "type_comment"]; -} impl From for Stmt { fn from(payload: StmtWith) -> Self { Stmt::With(payload) } } -impl From for Ast { - fn from(payload: StmtWith) -> Self { - Stmt::from(payload).into() - } -} /// See also [AsyncWith](https://docs.python.org/3/library/ast.html#ast.AsyncWith) #[derive(Clone, Debug, PartialEq)] @@ -739,20 +385,11 @@ pub struct StmtAsyncWith { pub type_comment: Option, } -impl Node for StmtAsyncWith { - const NAME: &'static str = "AsyncWith"; - const FIELD_NAMES: &'static [&'static str] = &["items", "body", "type_comment"]; -} impl From for Stmt { fn from(payload: StmtAsyncWith) -> Self { Stmt::AsyncWith(payload) } } -impl From for Ast { - fn from(payload: StmtAsyncWith) -> Self { - Stmt::from(payload).into() - } -} /// See also [Match](https://docs.python.org/3/library/ast.html#ast.Match) #[derive(Clone, Debug, PartialEq)] @@ -762,20 +399,11 @@ pub struct StmtMatch { pub cases: Vec, } -impl Node for StmtMatch { - const NAME: &'static str = "Match"; - const FIELD_NAMES: &'static [&'static str] = &["subject", "cases"]; -} impl From for Stmt { fn from(payload: StmtMatch) -> Self { Stmt::Match(payload) } } -impl From for Ast { - fn from(payload: StmtMatch) -> Self { - Stmt::from(payload).into() - } -} /// See also [Raise](https://docs.python.org/3/library/ast.html#ast.Raise) #[derive(Clone, Debug, PartialEq)] @@ -785,20 +413,11 @@ pub struct StmtRaise { pub cause: Option>, } -impl Node for StmtRaise { - const NAME: &'static str = "Raise"; - const FIELD_NAMES: &'static [&'static str] = &["exc", "cause"]; -} impl From for Stmt { fn from(payload: StmtRaise) -> Self { Stmt::Raise(payload) } } -impl From for Ast { - fn from(payload: StmtRaise) -> Self { - Stmt::from(payload).into() - } -} /// See also [Try](https://docs.python.org/3/library/ast.html#ast.Try) #[derive(Clone, Debug, PartialEq)] @@ -810,20 +429,11 @@ pub struct StmtTry { pub finalbody: Vec, } -impl Node for StmtTry { - const NAME: &'static str = "Try"; - const FIELD_NAMES: &'static [&'static str] = &["body", "handlers", "orelse", "finalbody"]; -} impl From for Stmt { fn from(payload: StmtTry) -> Self { Stmt::Try(payload) } } -impl From for Ast { - fn from(payload: StmtTry) -> Self { - Stmt::from(payload).into() - } -} /// See also [TryStar](https://docs.python.org/3/library/ast.html#ast.TryStar) #[derive(Clone, Debug, PartialEq)] @@ -835,20 +445,11 @@ pub struct StmtTryStar { pub finalbody: Vec, } -impl Node for StmtTryStar { - const NAME: &'static str = "TryStar"; - const FIELD_NAMES: &'static [&'static str] = &["body", "handlers", "orelse", "finalbody"]; -} impl From for Stmt { fn from(payload: StmtTryStar) -> Self { Stmt::TryStar(payload) } } -impl From for Ast { - fn from(payload: StmtTryStar) -> Self { - Stmt::from(payload).into() - } -} /// See also [Assert](https://docs.python.org/3/library/ast.html#ast.Assert) #[derive(Clone, Debug, PartialEq)] @@ -858,20 +459,11 @@ pub struct StmtAssert { pub msg: Option>, } -impl Node for StmtAssert { - const NAME: &'static str = "Assert"; - const FIELD_NAMES: &'static [&'static str] = &["test", "msg"]; -} impl From for Stmt { fn from(payload: StmtAssert) -> Self { Stmt::Assert(payload) } } -impl From for Ast { - fn from(payload: StmtAssert) -> Self { - Stmt::from(payload).into() - } -} /// See also [Import](https://docs.python.org/3/library/ast.html#ast.Import) #[derive(Clone, Debug, PartialEq)] @@ -880,20 +472,11 @@ pub struct StmtImport { pub names: Vec, } -impl Node for StmtImport { - const NAME: &'static str = "Import"; - const FIELD_NAMES: &'static [&'static str] = &["names"]; -} impl From for Stmt { fn from(payload: StmtImport) -> Self { Stmt::Import(payload) } } -impl From for Ast { - fn from(payload: StmtImport) -> Self { - Stmt::from(payload).into() - } -} /// See also [ImportFrom](https://docs.python.org/3/library/ast.html#ast.ImportFrom) #[derive(Clone, Debug, PartialEq)] @@ -904,20 +487,11 @@ pub struct StmtImportFrom { pub level: Option, } -impl Node for StmtImportFrom { - const NAME: &'static str = "ImportFrom"; - const FIELD_NAMES: &'static [&'static str] = &["module", "names", "level"]; -} impl From for Stmt { fn from(payload: StmtImportFrom) -> Self { Stmt::ImportFrom(payload) } } -impl From for Ast { - fn from(payload: StmtImportFrom) -> Self { - Stmt::from(payload).into() - } -} /// See also [Global](https://docs.python.org/3/library/ast.html#ast.Global) #[derive(Clone, Debug, PartialEq)] @@ -926,20 +500,11 @@ pub struct StmtGlobal { pub names: Vec, } -impl Node for StmtGlobal { - const NAME: &'static str = "Global"; - const FIELD_NAMES: &'static [&'static str] = &["names"]; -} impl From for Stmt { fn from(payload: StmtGlobal) -> Self { Stmt::Global(payload) } } -impl From for Ast { - fn from(payload: StmtGlobal) -> Self { - Stmt::from(payload).into() - } -} /// See also [Nonlocal](https://docs.python.org/3/library/ast.html#ast.Nonlocal) #[derive(Clone, Debug, PartialEq)] @@ -948,20 +513,11 @@ pub struct StmtNonlocal { pub names: Vec, } -impl Node for StmtNonlocal { - const NAME: &'static str = "Nonlocal"; - const FIELD_NAMES: &'static [&'static str] = &["names"]; -} impl From for Stmt { fn from(payload: StmtNonlocal) -> Self { Stmt::Nonlocal(payload) } } -impl From for Ast { - fn from(payload: StmtNonlocal) -> Self { - Stmt::from(payload).into() - } -} /// See also [Expr](https://docs.python.org/3/library/ast.html#ast.Expr) #[derive(Clone, Debug, PartialEq)] @@ -970,20 +526,11 @@ pub struct StmtExpr { pub value: Box, } -impl Node for StmtExpr { - const NAME: &'static str = "Expr"; - const FIELD_NAMES: &'static [&'static str] = &["value"]; -} impl From for Stmt { fn from(payload: StmtExpr) -> Self { Stmt::Expr(payload) } } -impl From for Ast { - fn from(payload: StmtExpr) -> Self { - Stmt::from(payload).into() - } -} /// See also [Pass](https://docs.python.org/3/library/ast.html#ast.Pass) #[derive(Clone, Debug, PartialEq)] @@ -991,20 +538,11 @@ pub struct StmtPass { pub range: TextRange, } -impl Node for StmtPass { - const NAME: &'static str = "Pass"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} impl From for Stmt { fn from(payload: StmtPass) -> Self { Stmt::Pass(payload) } } -impl From for Ast { - fn from(payload: StmtPass) -> Self { - Stmt::from(payload).into() - } -} /// See also [Break](https://docs.python.org/3/library/ast.html#ast.Break) #[derive(Clone, Debug, PartialEq)] @@ -1012,20 +550,11 @@ pub struct StmtBreak { pub range: TextRange, } -impl Node for StmtBreak { - const NAME: &'static str = "Break"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} impl From for Stmt { fn from(payload: StmtBreak) -> Self { Stmt::Break(payload) } } -impl From for Ast { - fn from(payload: StmtBreak) -> Self { - Stmt::from(payload).into() - } -} /// See also [Continue](https://docs.python.org/3/library/ast.html#ast.Continue) #[derive(Clone, Debug, PartialEq)] @@ -1033,25 +562,11 @@ pub struct StmtContinue { pub range: TextRange, } -impl Node for StmtContinue { - const NAME: &'static str = "Continue"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} impl From for Stmt { fn from(payload: StmtContinue) -> Self { Stmt::Continue(payload) } } -impl From for Ast { - fn from(payload: StmtContinue) -> Self { - Stmt::from(payload).into() - } -} - -impl Node for Stmt { - const NAME: &'static str = "stmt"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} /// See also [expr](https://docs.python.org/3/library/ast.html#ast.expr) #[derive(Clone, Debug, PartialEq, is_macro::Is)] @@ -1123,20 +638,11 @@ pub struct ExprLineMagic { pub value: String, } -impl Node for ExprLineMagic { - const NAME: &'static str = "LineMagic"; - const FIELD_NAMES: &'static [&'static str] = &["kind", "value"]; -} impl From for Expr { fn from(payload: ExprLineMagic) -> Self { Expr::LineMagic(payload) } } -impl From for Ast { - fn from(payload: ExprLineMagic) -> Self { - Expr::from(payload).into() - } -} /// See also [BoolOp](https://docs.python.org/3/library/ast.html#ast.BoolOp) #[derive(Clone, Debug, PartialEq)] @@ -1146,20 +652,11 @@ pub struct ExprBoolOp { pub values: Vec, } -impl Node for ExprBoolOp { - const NAME: &'static str = "BoolOp"; - const FIELD_NAMES: &'static [&'static str] = &["op", "values"]; -} impl From for Expr { fn from(payload: ExprBoolOp) -> Self { Expr::BoolOp(payload) } } -impl From for Ast { - fn from(payload: ExprBoolOp) -> Self { - Expr::from(payload).into() - } -} /// See also [NamedExpr](https://docs.python.org/3/library/ast.html#ast.NamedExpr) #[derive(Clone, Debug, PartialEq)] @@ -1169,20 +666,11 @@ pub struct ExprNamedExpr { pub value: Box, } -impl Node for ExprNamedExpr { - const NAME: &'static str = "NamedExpr"; - const FIELD_NAMES: &'static [&'static str] = &["target", "value"]; -} impl From for Expr { fn from(payload: ExprNamedExpr) -> Self { Expr::NamedExpr(payload) } } -impl From for Ast { - fn from(payload: ExprNamedExpr) -> Self { - Expr::from(payload).into() - } -} /// See also [BinOp](https://docs.python.org/3/library/ast.html#ast.BinOp) #[derive(Clone, Debug, PartialEq)] @@ -1193,20 +681,11 @@ pub struct ExprBinOp { pub right: Box, } -impl Node for ExprBinOp { - const NAME: &'static str = "BinOp"; - const FIELD_NAMES: &'static [&'static str] = &["left", "op", "right"]; -} impl From for Expr { fn from(payload: ExprBinOp) -> Self { Expr::BinOp(payload) } } -impl From for Ast { - fn from(payload: ExprBinOp) -> Self { - Expr::from(payload).into() - } -} /// See also [UnaryOp](https://docs.python.org/3/library/ast.html#ast.UnaryOp) #[derive(Clone, Debug, PartialEq)] @@ -1216,20 +695,11 @@ pub struct ExprUnaryOp { pub operand: Box, } -impl Node for ExprUnaryOp { - const NAME: &'static str = "UnaryOp"; - const FIELD_NAMES: &'static [&'static str] = &["op", "operand"]; -} impl From for Expr { fn from(payload: ExprUnaryOp) -> Self { Expr::UnaryOp(payload) } } -impl From for Ast { - fn from(payload: ExprUnaryOp) -> Self { - Expr::from(payload).into() - } -} /// See also [Lambda](https://docs.python.org/3/library/ast.html#ast.Lambda) #[derive(Clone, Debug, PartialEq)] @@ -1239,20 +709,11 @@ pub struct ExprLambda { pub body: Box, } -impl Node for ExprLambda { - const NAME: &'static str = "Lambda"; - const FIELD_NAMES: &'static [&'static str] = &["args", "body"]; -} impl From for Expr { fn from(payload: ExprLambda) -> Self { Expr::Lambda(payload) } } -impl From for Ast { - fn from(payload: ExprLambda) -> Self { - Expr::from(payload).into() - } -} /// See also [IfExp](https://docs.python.org/3/library/ast.html#ast.IfExp) #[derive(Clone, Debug, PartialEq)] @@ -1263,20 +724,11 @@ pub struct ExprIfExp { pub orelse: Box, } -impl Node for ExprIfExp { - const NAME: &'static str = "IfExp"; - const FIELD_NAMES: &'static [&'static str] = &["test", "body", "orelse"]; -} impl From for Expr { fn from(payload: ExprIfExp) -> Self { Expr::IfExp(payload) } } -impl From for Ast { - fn from(payload: ExprIfExp) -> Self { - Expr::from(payload).into() - } -} /// See also [Dict](https://docs.python.org/3/library/ast.html#ast.Dict) #[derive(Clone, Debug, PartialEq)] @@ -1286,20 +738,11 @@ pub struct ExprDict { pub values: Vec, } -impl Node for ExprDict { - const NAME: &'static str = "Dict"; - const FIELD_NAMES: &'static [&'static str] = &["keys", "values"]; -} impl From for Expr { fn from(payload: ExprDict) -> Self { Expr::Dict(payload) } } -impl From for Ast { - fn from(payload: ExprDict) -> Self { - Expr::from(payload).into() - } -} /// See also [Set](https://docs.python.org/3/library/ast.html#ast.Set) #[derive(Clone, Debug, PartialEq)] @@ -1308,20 +751,11 @@ pub struct ExprSet { pub elts: Vec, } -impl Node for ExprSet { - const NAME: &'static str = "Set"; - const FIELD_NAMES: &'static [&'static str] = &["elts"]; -} impl From for Expr { fn from(payload: ExprSet) -> Self { Expr::Set(payload) } } -impl From for Ast { - fn from(payload: ExprSet) -> Self { - Expr::from(payload).into() - } -} /// See also [ListComp](https://docs.python.org/3/library/ast.html#ast.ListComp) #[derive(Clone, Debug, PartialEq)] @@ -1331,20 +765,11 @@ pub struct ExprListComp { pub generators: Vec, } -impl Node for ExprListComp { - const NAME: &'static str = "ListComp"; - const FIELD_NAMES: &'static [&'static str] = &["elt", "generators"]; -} impl From for Expr { fn from(payload: ExprListComp) -> Self { Expr::ListComp(payload) } } -impl From for Ast { - fn from(payload: ExprListComp) -> Self { - Expr::from(payload).into() - } -} /// See also [SetComp](https://docs.python.org/3/library/ast.html#ast.SetComp) #[derive(Clone, Debug, PartialEq)] @@ -1354,20 +779,11 @@ pub struct ExprSetComp { pub generators: Vec, } -impl Node for ExprSetComp { - const NAME: &'static str = "SetComp"; - const FIELD_NAMES: &'static [&'static str] = &["elt", "generators"]; -} impl From for Expr { fn from(payload: ExprSetComp) -> Self { Expr::SetComp(payload) } } -impl From for Ast { - fn from(payload: ExprSetComp) -> Self { - Expr::from(payload).into() - } -} /// See also [DictComp](https://docs.python.org/3/library/ast.html#ast.DictComp) #[derive(Clone, Debug, PartialEq)] @@ -1378,20 +794,11 @@ pub struct ExprDictComp { pub generators: Vec, } -impl Node for ExprDictComp { - const NAME: &'static str = "DictComp"; - const FIELD_NAMES: &'static [&'static str] = &["key", "value", "generators"]; -} impl From for Expr { fn from(payload: ExprDictComp) -> Self { Expr::DictComp(payload) } } -impl From for Ast { - fn from(payload: ExprDictComp) -> Self { - Expr::from(payload).into() - } -} /// See also [GeneratorExp](https://docs.python.org/3/library/ast.html#ast.GeneratorExp) #[derive(Clone, Debug, PartialEq)] @@ -1401,20 +808,11 @@ pub struct ExprGeneratorExp { pub generators: Vec, } -impl Node for ExprGeneratorExp { - const NAME: &'static str = "GeneratorExp"; - const FIELD_NAMES: &'static [&'static str] = &["elt", "generators"]; -} impl From for Expr { fn from(payload: ExprGeneratorExp) -> Self { Expr::GeneratorExp(payload) } } -impl From for Ast { - fn from(payload: ExprGeneratorExp) -> Self { - Expr::from(payload).into() - } -} /// See also [Await](https://docs.python.org/3/library/ast.html#ast.Await) #[derive(Clone, Debug, PartialEq)] @@ -1423,20 +821,11 @@ pub struct ExprAwait { pub value: Box, } -impl Node for ExprAwait { - const NAME: &'static str = "Await"; - const FIELD_NAMES: &'static [&'static str] = &["value"]; -} impl From for Expr { fn from(payload: ExprAwait) -> Self { Expr::Await(payload) } } -impl From for Ast { - fn from(payload: ExprAwait) -> Self { - Expr::from(payload).into() - } -} /// See also [Yield](https://docs.python.org/3/library/ast.html#ast.Yield) #[derive(Clone, Debug, PartialEq)] @@ -1445,20 +834,11 @@ pub struct ExprYield { pub value: Option>, } -impl Node for ExprYield { - const NAME: &'static str = "Yield"; - const FIELD_NAMES: &'static [&'static str] = &["value"]; -} impl From for Expr { fn from(payload: ExprYield) -> Self { Expr::Yield(payload) } } -impl From for Ast { - fn from(payload: ExprYield) -> Self { - Expr::from(payload).into() - } -} /// See also [YieldFrom](https://docs.python.org/3/library/ast.html#ast.YieldFrom) #[derive(Clone, Debug, PartialEq)] @@ -1467,20 +847,11 @@ pub struct ExprYieldFrom { pub value: Box, } -impl Node for ExprYieldFrom { - const NAME: &'static str = "YieldFrom"; - const FIELD_NAMES: &'static [&'static str] = &["value"]; -} impl From for Expr { fn from(payload: ExprYieldFrom) -> Self { Expr::YieldFrom(payload) } } -impl From for Ast { - fn from(payload: ExprYieldFrom) -> Self { - Expr::from(payload).into() - } -} /// See also [Compare](https://docs.python.org/3/library/ast.html#ast.Compare) #[derive(Clone, Debug, PartialEq)] @@ -1491,20 +862,11 @@ pub struct ExprCompare { pub comparators: Vec, } -impl Node for ExprCompare { - const NAME: &'static str = "Compare"; - const FIELD_NAMES: &'static [&'static str] = &["left", "ops", "comparators"]; -} impl From for Expr { fn from(payload: ExprCompare) -> Self { Expr::Compare(payload) } } -impl From for Ast { - fn from(payload: ExprCompare) -> Self { - Expr::from(payload).into() - } -} /// See also [Call](https://docs.python.org/3/library/ast.html#ast.Call) #[derive(Clone, Debug, PartialEq)] @@ -1515,20 +877,11 @@ pub struct ExprCall { pub keywords: Vec, } -impl Node for ExprCall { - const NAME: &'static str = "Call"; - const FIELD_NAMES: &'static [&'static str] = &["func", "args", "keywords"]; -} impl From for Expr { fn from(payload: ExprCall) -> Self { Expr::Call(payload) } } -impl From for Ast { - fn from(payload: ExprCall) -> Self { - Expr::from(payload).into() - } -} /// See also [FormattedValue](https://docs.python.org/3/library/ast.html#ast.FormattedValue) #[derive(Clone, Debug, PartialEq)] @@ -1539,18 +892,35 @@ pub struct ExprFormattedValue { pub format_spec: Option>, } -impl Node for ExprFormattedValue { - const NAME: &'static str = "FormattedValue"; - const FIELD_NAMES: &'static [&'static str] = &["value", "conversion", "format_spec"]; -} impl From for Expr { fn from(payload: ExprFormattedValue) -> Self { Expr::FormattedValue(payload) } } -impl From for Ast { - fn from(payload: ExprFormattedValue) -> Self { - Expr::from(payload).into() + +/// Transforms a value prior to formatting it. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, is_macro::Is)] +#[repr(i8)] +pub enum ConversionFlag { + /// No conversion + None = -1, // CPython uses -1 + /// Converts by calling `str()`. + Str = b's' as i8, + /// Converts by calling `ascii()`. + Ascii = b'a' as i8, + /// Converts by calling `repr()`. + Repr = b'r' as i8, +} + +impl ConversionFlag { + pub fn to_byte(&self) -> Option { + match self { + Self::None => None, + flag => Some(*flag as u8), + } + } + pub fn to_char(&self) -> Option { + Some(self.to_byte()? as char) } } @@ -1561,20 +931,11 @@ pub struct ExprJoinedStr { pub values: Vec, } -impl Node for ExprJoinedStr { - const NAME: &'static str = "JoinedStr"; - const FIELD_NAMES: &'static [&'static str] = &["values"]; -} impl From for Expr { fn from(payload: ExprJoinedStr) -> Self { Expr::JoinedStr(payload) } } -impl From for Ast { - fn from(payload: ExprJoinedStr) -> Self { - Expr::from(payload).into() - } -} /// See also [Constant](https://docs.python.org/3/library/ast.html#ast.Constant) #[derive(Clone, Debug, PartialEq)] @@ -1584,20 +945,11 @@ pub struct ExprConstant { pub kind: Option, } -impl Node for ExprConstant { - const NAME: &'static str = "Constant"; - const FIELD_NAMES: &'static [&'static str] = &["value", "kind"]; -} impl From for Expr { fn from(payload: ExprConstant) -> Self { Expr::Constant(payload) } } -impl From for Ast { - fn from(payload: ExprConstant) -> Self { - Expr::from(payload).into() - } -} /// See also [Attribute](https://docs.python.org/3/library/ast.html#ast.Attribute) #[derive(Clone, Debug, PartialEq)] @@ -1608,20 +960,11 @@ pub struct ExprAttribute { pub ctx: ExprContext, } -impl Node for ExprAttribute { - const NAME: &'static str = "Attribute"; - const FIELD_NAMES: &'static [&'static str] = &["value", "attr", "ctx"]; -} impl From for Expr { fn from(payload: ExprAttribute) -> Self { Expr::Attribute(payload) } } -impl From for Ast { - fn from(payload: ExprAttribute) -> Self { - Expr::from(payload).into() - } -} /// See also [Subscript](https://docs.python.org/3/library/ast.html#ast.Subscript) #[derive(Clone, Debug, PartialEq)] @@ -1632,20 +975,11 @@ pub struct ExprSubscript { pub ctx: ExprContext, } -impl Node for ExprSubscript { - const NAME: &'static str = "Subscript"; - const FIELD_NAMES: &'static [&'static str] = &["value", "slice", "ctx"]; -} impl From for Expr { fn from(payload: ExprSubscript) -> Self { Expr::Subscript(payload) } } -impl From for Ast { - fn from(payload: ExprSubscript) -> Self { - Expr::from(payload).into() - } -} /// See also [Starred](https://docs.python.org/3/library/ast.html#ast.Starred) #[derive(Clone, Debug, PartialEq)] @@ -1655,20 +989,11 @@ pub struct ExprStarred { pub ctx: ExprContext, } -impl Node for ExprStarred { - const NAME: &'static str = "Starred"; - const FIELD_NAMES: &'static [&'static str] = &["value", "ctx"]; -} impl From for Expr { fn from(payload: ExprStarred) -> Self { Expr::Starred(payload) } } -impl From for Ast { - fn from(payload: ExprStarred) -> Self { - Expr::from(payload).into() - } -} /// See also [Name](https://docs.python.org/3/library/ast.html#ast.Name) #[derive(Clone, Debug, PartialEq)] @@ -1678,20 +1003,11 @@ pub struct ExprName { pub ctx: ExprContext, } -impl Node for ExprName { - const NAME: &'static str = "Name"; - const FIELD_NAMES: &'static [&'static str] = &["id", "ctx"]; -} impl From for Expr { fn from(payload: ExprName) -> Self { Expr::Name(payload) } } -impl From for Ast { - fn from(payload: ExprName) -> Self { - Expr::from(payload).into() - } -} /// See also [List](https://docs.python.org/3/library/ast.html#ast.List) #[derive(Clone, Debug, PartialEq)] @@ -1701,20 +1017,11 @@ pub struct ExprList { pub ctx: ExprContext, } -impl Node for ExprList { - const NAME: &'static str = "List"; - const FIELD_NAMES: &'static [&'static str] = &["elts", "ctx"]; -} impl From for Expr { fn from(payload: ExprList) -> Self { Expr::List(payload) } } -impl From for Ast { - fn from(payload: ExprList) -> Self { - Expr::from(payload).into() - } -} /// See also [Tuple](https://docs.python.org/3/library/ast.html#ast.Tuple) #[derive(Clone, Debug, PartialEq)] @@ -1724,20 +1031,11 @@ pub struct ExprTuple { pub ctx: ExprContext, } -impl Node for ExprTuple { - const NAME: &'static str = "Tuple"; - const FIELD_NAMES: &'static [&'static str] = &["elts", "ctx"]; -} impl From for Expr { fn from(payload: ExprTuple) -> Self { Expr::Tuple(payload) } } -impl From for Ast { - fn from(payload: ExprTuple) -> Self { - Expr::from(payload).into() - } -} /// See also [Slice](https://docs.python.org/3/library/ast.html#ast.Slice) #[derive(Clone, Debug, PartialEq)] @@ -1748,25 +1046,11 @@ pub struct ExprSlice { pub step: Option>, } -impl Node for ExprSlice { - const NAME: &'static str = "Slice"; - const FIELD_NAMES: &'static [&'static str] = &["lower", "upper", "step"]; -} impl From for Expr { fn from(payload: ExprSlice) -> Self { Expr::Slice(payload) } } -impl From for Ast { - fn from(payload: ExprSlice) -> Self { - Expr::from(payload).into() - } -} - -impl Node for Expr { - const NAME: &'static str = "expr"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} /// See also [expr_context](https://docs.python.org/3/library/ast.html#ast.expr_context) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] @@ -1807,15 +1091,7 @@ impl From for ExprContext { ExprContext::Load } } -impl From for Ast { - fn from(_: ExprContextLoad) -> Self { - ExprContext::Load.into() - } -} -impl Node for ExprContextLoad { - const NAME: &'static str = "Load"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for ExprContextLoad { #[inline] fn eq(&self, other: &ExprContext) -> bool { @@ -1829,15 +1105,7 @@ impl From for ExprContext { ExprContext::Store } } -impl From for Ast { - fn from(_: ExprContextStore) -> Self { - ExprContext::Store.into() - } -} -impl Node for ExprContextStore { - const NAME: &'static str = "Store"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for ExprContextStore { #[inline] fn eq(&self, other: &ExprContext) -> bool { @@ -1851,15 +1119,7 @@ impl From for ExprContext { ExprContext::Del } } -impl From for Ast { - fn from(_: ExprContextDel) -> Self { - ExprContext::Del.into() - } -} -impl Node for ExprContextDel { - const NAME: &'static str = "Del"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for ExprContextDel { #[inline] fn eq(&self, other: &ExprContext) -> bool { @@ -1867,11 +1127,6 @@ impl std::cmp::PartialEq for ExprContextDel { } } -impl Node for ExprContext { - const NAME: &'static str = "expr_context"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} - /// See also [boolop](https://docs.python.org/3/library/ast.html#ast.BoolOp) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum BoolOp { @@ -1902,15 +1157,7 @@ impl From for BoolOp { BoolOp::And } } -impl From for Ast { - fn from(_: BoolOpAnd) -> Self { - BoolOp::And.into() - } -} -impl Node for BoolOpAnd { - const NAME: &'static str = "And"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for BoolOpAnd { #[inline] fn eq(&self, other: &BoolOp) -> bool { @@ -1924,15 +1171,7 @@ impl From for BoolOp { BoolOp::Or } } -impl From for Ast { - fn from(_: BoolOpOr) -> Self { - BoolOp::Or.into() - } -} -impl Node for BoolOpOr { - const NAME: &'static str = "Or"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for BoolOpOr { #[inline] fn eq(&self, other: &BoolOp) -> bool { @@ -1940,11 +1179,6 @@ impl std::cmp::PartialEq for BoolOpOr { } } -impl Node for BoolOp { - const NAME: &'static str = "boolop"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} - /// See also [operator](https://docs.python.org/3/library/ast.html#ast.operator) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum Operator { @@ -2074,15 +1308,7 @@ impl From for Operator { Operator::Add } } -impl From for Ast { - fn from(_: OperatorAdd) -> Self { - Operator::Add.into() - } -} -impl Node for OperatorAdd { - const NAME: &'static str = "Add"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorAdd { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2096,15 +1322,7 @@ impl From for Operator { Operator::Sub } } -impl From for Ast { - fn from(_: OperatorSub) -> Self { - Operator::Sub.into() - } -} -impl Node for OperatorSub { - const NAME: &'static str = "Sub"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorSub { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2118,15 +1336,7 @@ impl From for Operator { Operator::Mult } } -impl From for Ast { - fn from(_: OperatorMult) -> Self { - Operator::Mult.into() - } -} -impl Node for OperatorMult { - const NAME: &'static str = "Mult"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorMult { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2140,15 +1350,7 @@ impl From for Operator { Operator::MatMult } } -impl From for Ast { - fn from(_: OperatorMatMult) -> Self { - Operator::MatMult.into() - } -} -impl Node for OperatorMatMult { - const NAME: &'static str = "MatMult"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorMatMult { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2162,15 +1364,7 @@ impl From for Operator { Operator::Div } } -impl From for Ast { - fn from(_: OperatorDiv) -> Self { - Operator::Div.into() - } -} -impl Node for OperatorDiv { - const NAME: &'static str = "Div"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorDiv { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2184,15 +1378,7 @@ impl From for Operator { Operator::Mod } } -impl From for Ast { - fn from(_: OperatorMod) -> Self { - Operator::Mod.into() - } -} -impl Node for OperatorMod { - const NAME: &'static str = "Mod"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorMod { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2206,15 +1392,7 @@ impl From for Operator { Operator::Pow } } -impl From for Ast { - fn from(_: OperatorPow) -> Self { - Operator::Pow.into() - } -} -impl Node for OperatorPow { - const NAME: &'static str = "Pow"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorPow { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2228,15 +1406,7 @@ impl From for Operator { Operator::LShift } } -impl From for Ast { - fn from(_: OperatorLShift) -> Self { - Operator::LShift.into() - } -} -impl Node for OperatorLShift { - const NAME: &'static str = "LShift"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorLShift { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2250,15 +1420,7 @@ impl From for Operator { Operator::RShift } } -impl From for Ast { - fn from(_: OperatorRShift) -> Self { - Operator::RShift.into() - } -} -impl Node for OperatorRShift { - const NAME: &'static str = "RShift"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorRShift { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2272,15 +1434,7 @@ impl From for Operator { Operator::BitOr } } -impl From for Ast { - fn from(_: OperatorBitOr) -> Self { - Operator::BitOr.into() - } -} -impl Node for OperatorBitOr { - const NAME: &'static str = "BitOr"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorBitOr { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2294,15 +1448,7 @@ impl From for Operator { Operator::BitXor } } -impl From for Ast { - fn from(_: OperatorBitXor) -> Self { - Operator::BitXor.into() - } -} -impl Node for OperatorBitXor { - const NAME: &'static str = "BitXor"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorBitXor { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2316,15 +1462,7 @@ impl From for Operator { Operator::BitAnd } } -impl From for Ast { - fn from(_: OperatorBitAnd) -> Self { - Operator::BitAnd.into() - } -} -impl Node for OperatorBitAnd { - const NAME: &'static str = "BitAnd"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorBitAnd { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2338,15 +1476,7 @@ impl From for Operator { Operator::FloorDiv } } -impl From for Ast { - fn from(_: OperatorFloorDiv) -> Self { - Operator::FloorDiv.into() - } -} -impl Node for OperatorFloorDiv { - const NAME: &'static str = "FloorDiv"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for OperatorFloorDiv { #[inline] fn eq(&self, other: &Operator) -> bool { @@ -2354,11 +1484,6 @@ impl std::cmp::PartialEq for OperatorFloorDiv { } } -impl Node for Operator { - const NAME: &'static str = "operator"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} - /// See also [unaryop](https://docs.python.org/3/library/ast.html#ast.unaryop) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum UnaryOp { @@ -2407,15 +1532,7 @@ impl From for UnaryOp { UnaryOp::Invert } } -impl From for Ast { - fn from(_: UnaryOpInvert) -> Self { - UnaryOp::Invert.into() - } -} -impl Node for UnaryOpInvert { - const NAME: &'static str = "Invert"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for UnaryOpInvert { #[inline] fn eq(&self, other: &UnaryOp) -> bool { @@ -2429,15 +1546,7 @@ impl From for UnaryOp { UnaryOp::Not } } -impl From for Ast { - fn from(_: UnaryOpNot) -> Self { - UnaryOp::Not.into() - } -} -impl Node for UnaryOpNot { - const NAME: &'static str = "Not"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for UnaryOpNot { #[inline] fn eq(&self, other: &UnaryOp) -> bool { @@ -2451,15 +1560,7 @@ impl From for UnaryOp { UnaryOp::UAdd } } -impl From for Ast { - fn from(_: UnaryOpUAdd) -> Self { - UnaryOp::UAdd.into() - } -} -impl Node for UnaryOpUAdd { - const NAME: &'static str = "UAdd"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for UnaryOpUAdd { #[inline] fn eq(&self, other: &UnaryOp) -> bool { @@ -2473,15 +1574,7 @@ impl From for UnaryOp { UnaryOp::USub } } -impl From for Ast { - fn from(_: UnaryOpUSub) -> Self { - UnaryOp::USub.into() - } -} -impl Node for UnaryOpUSub { - const NAME: &'static str = "USub"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for UnaryOpUSub { #[inline] fn eq(&self, other: &UnaryOp) -> bool { @@ -2489,11 +1582,6 @@ impl std::cmp::PartialEq for UnaryOpUSub { } } -impl Node for UnaryOp { - const NAME: &'static str = "unaryop"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} - /// See also [cmpop](https://docs.python.org/3/library/ast.html#ast.cmpop) #[derive(Clone, Debug, PartialEq, is_macro::Is, Copy, Hash, Eq)] pub enum CmpOp { @@ -2596,15 +1684,7 @@ impl From for CmpOp { CmpOp::Eq } } -impl From for Ast { - fn from(_: CmpOpEq) -> Self { - CmpOp::Eq.into() - } -} -impl Node for CmpOpEq { - const NAME: &'static str = "Eq"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpEq { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2618,15 +1698,7 @@ impl From for CmpOp { CmpOp::NotEq } } -impl From for Ast { - fn from(_: CmpOpNotEq) -> Self { - CmpOp::NotEq.into() - } -} -impl Node for CmpOpNotEq { - const NAME: &'static str = "NotEq"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpNotEq { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2640,15 +1712,7 @@ impl From for CmpOp { CmpOp::Lt } } -impl From for Ast { - fn from(_: CmpOpLt) -> Self { - CmpOp::Lt.into() - } -} -impl Node for CmpOpLt { - const NAME: &'static str = "Lt"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpLt { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2662,15 +1726,7 @@ impl From for CmpOp { CmpOp::LtE } } -impl From for Ast { - fn from(_: CmpOpLtE) -> Self { - CmpOp::LtE.into() - } -} -impl Node for CmpOpLtE { - const NAME: &'static str = "LtE"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpLtE { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2684,15 +1740,7 @@ impl From for CmpOp { CmpOp::Gt } } -impl From for Ast { - fn from(_: CmpOpGt) -> Self { - CmpOp::Gt.into() - } -} -impl Node for CmpOpGt { - const NAME: &'static str = "Gt"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpGt { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2706,15 +1754,7 @@ impl From for CmpOp { CmpOp::GtE } } -impl From for Ast { - fn from(_: CmpOpGtE) -> Self { - CmpOp::GtE.into() - } -} -impl Node for CmpOpGtE { - const NAME: &'static str = "GtE"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpGtE { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2728,15 +1768,7 @@ impl From for CmpOp { CmpOp::Is } } -impl From for Ast { - fn from(_: CmpOpIs) -> Self { - CmpOp::Is.into() - } -} -impl Node for CmpOpIs { - const NAME: &'static str = "Is"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpIs { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2750,15 +1782,7 @@ impl From for CmpOp { CmpOp::IsNot } } -impl From for Ast { - fn from(_: CmpOpIsNot) -> Self { - CmpOp::IsNot.into() - } -} -impl Node for CmpOpIsNot { - const NAME: &'static str = "IsNot"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpIsNot { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2772,15 +1796,7 @@ impl From for CmpOp { CmpOp::In } } -impl From for Ast { - fn from(_: CmpOpIn) -> Self { - CmpOp::In.into() - } -} -impl Node for CmpOpIn { - const NAME: &'static str = "In"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpIn { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2794,15 +1810,7 @@ impl From for CmpOp { CmpOp::NotIn } } -impl From for Ast { - fn from(_: CmpOpNotIn) -> Self { - CmpOp::NotIn.into() - } -} -impl Node for CmpOpNotIn { - const NAME: &'static str = "NotIn"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} + impl std::cmp::PartialEq for CmpOpNotIn { #[inline] fn eq(&self, other: &CmpOp) -> bool { @@ -2810,11 +1818,6 @@ impl std::cmp::PartialEq for CmpOpNotIn { } } -impl Node for CmpOp { - const NAME: &'static str = "cmpop"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} - /// See also [comprehension](https://docs.python.org/3/library/ast.html#ast.comprehension) #[derive(Clone, Debug, PartialEq)] pub struct Comprehension { @@ -2825,11 +1828,6 @@ pub struct Comprehension { pub is_async: bool, } -impl Node for Comprehension { - const NAME: &'static str = "comprehension"; - const FIELD_NAMES: &'static [&'static str] = &["target", "iter", "ifs", "is_async"]; -} - /// See also [excepthandler](https://docs.python.org/3/library/ast.html#ast.excepthandler) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum ExceptHandler { @@ -2845,25 +1843,11 @@ pub struct ExceptHandlerExceptHandler { pub body: Vec, } -impl Node for ExceptHandlerExceptHandler { - const NAME: &'static str = "ExceptHandler"; - const FIELD_NAMES: &'static [&'static str] = &["type", "name", "body"]; -} impl From for ExceptHandler { fn from(payload: ExceptHandlerExceptHandler) -> Self { ExceptHandler::ExceptHandler(payload) } } -impl From for Ast { - fn from(payload: ExceptHandlerExceptHandler) -> Self { - ExceptHandler::from(payload).into() - } -} - -impl Node for ExceptHandler { - const NAME: &'static str = "excepthandler"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} /// See also [arguments](https://docs.python.org/3/library/ast.html#ast.arguments) #[derive(Clone, Debug, PartialEq)] @@ -2878,19 +1862,6 @@ pub struct PythonArguments { pub defaults: Vec, } -impl Node for PythonArguments { - const NAME: &'static str = "arguments"; - const FIELD_NAMES: &'static [&'static str] = &[ - "posonlyargs", - "args", - "vararg", - "kwonlyargs", - "kw_defaults", - "kwarg", - "defaults", - ]; -} - /// See also [arg](https://docs.python.org/3/library/ast.html#ast.arg) #[derive(Clone, Debug, PartialEq)] pub struct Arg { @@ -2900,11 +1871,6 @@ pub struct Arg { pub type_comment: Option, } -impl Node for Arg { - const NAME: &'static str = "arg"; - const FIELD_NAMES: &'static [&'static str] = &["arg", "annotation", "type_comment"]; -} - /// See also [keyword](https://docs.python.org/3/library/ast.html#ast.keyword) #[derive(Clone, Debug, PartialEq)] pub struct Keyword { @@ -2913,11 +1879,6 @@ pub struct Keyword { pub value: Expr, } -impl Node for Keyword { - const NAME: &'static str = "keyword"; - const FIELD_NAMES: &'static [&'static str] = &["arg", "value"]; -} - /// See also [alias](https://docs.python.org/3/library/ast.html#ast.alias) #[derive(Clone, Debug, PartialEq)] pub struct Alias { @@ -2926,11 +1887,6 @@ pub struct Alias { pub asname: Option, } -impl Node for Alias { - const NAME: &'static str = "alias"; - const FIELD_NAMES: &'static [&'static str] = &["name", "asname"]; -} - /// See also [withitem](https://docs.python.org/3/library/ast.html#ast.withitem) #[derive(Clone, Debug, PartialEq)] pub struct WithItem { @@ -2939,11 +1895,6 @@ pub struct WithItem { pub optional_vars: Option>, } -impl Node for WithItem { - const NAME: &'static str = "withitem"; - const FIELD_NAMES: &'static [&'static str] = &["context_expr", "optional_vars"]; -} - /// See also [match_case](https://docs.python.org/3/library/ast.html#ast.match_case) #[derive(Clone, Debug, PartialEq)] pub struct MatchCase { @@ -2953,11 +1904,6 @@ pub struct MatchCase { pub body: Vec, } -impl Node for MatchCase { - const NAME: &'static str = "match_case"; - const FIELD_NAMES: &'static [&'static str] = &["pattern", "guard", "body"]; -} - /// See also [pattern](https://docs.python.org/3/library/ast.html#ast.pattern) #[derive(Clone, Debug, PartialEq, is_macro::Is)] pub enum Pattern { @@ -2978,20 +1924,11 @@ pub struct PatternMatchValue { pub value: Box, } -impl Node for PatternMatchValue { - const NAME: &'static str = "MatchValue"; - const FIELD_NAMES: &'static [&'static str] = &["value"]; -} impl From for Pattern { fn from(payload: PatternMatchValue) -> Self { Pattern::MatchValue(payload) } } -impl From for Ast { - fn from(payload: PatternMatchValue) -> Self { - Pattern::from(payload).into() - } -} /// See also [MatchSingleton](https://docs.python.org/3/library/ast.html#ast.MatchSingleton) #[derive(Clone, Debug, PartialEq)] @@ -3000,20 +1937,11 @@ pub struct PatternMatchSingleton { pub value: Constant, } -impl Node for PatternMatchSingleton { - const NAME: &'static str = "MatchSingleton"; - const FIELD_NAMES: &'static [&'static str] = &["value"]; -} impl From for Pattern { fn from(payload: PatternMatchSingleton) -> Self { Pattern::MatchSingleton(payload) } } -impl From for Ast { - fn from(payload: PatternMatchSingleton) -> Self { - Pattern::from(payload).into() - } -} /// See also [MatchSequence](https://docs.python.org/3/library/ast.html#ast.MatchSequence) #[derive(Clone, Debug, PartialEq)] @@ -3022,20 +1950,11 @@ pub struct PatternMatchSequence { pub patterns: Vec, } -impl Node for PatternMatchSequence { - const NAME: &'static str = "MatchSequence"; - const FIELD_NAMES: &'static [&'static str] = &["patterns"]; -} impl From for Pattern { fn from(payload: PatternMatchSequence) -> Self { Pattern::MatchSequence(payload) } } -impl From for Ast { - fn from(payload: PatternMatchSequence) -> Self { - Pattern::from(payload).into() - } -} /// See also [MatchMapping](https://docs.python.org/3/library/ast.html#ast.MatchMapping) #[derive(Clone, Debug, PartialEq)] @@ -3046,20 +1965,11 @@ pub struct PatternMatchMapping { pub rest: Option, } -impl Node for PatternMatchMapping { - const NAME: &'static str = "MatchMapping"; - const FIELD_NAMES: &'static [&'static str] = &["keys", "patterns", "rest"]; -} impl From for Pattern { fn from(payload: PatternMatchMapping) -> Self { Pattern::MatchMapping(payload) } } -impl From for Ast { - fn from(payload: PatternMatchMapping) -> Self { - Pattern::from(payload).into() - } -} /// See also [MatchClass](https://docs.python.org/3/library/ast.html#ast.MatchClass) #[derive(Clone, Debug, PartialEq)] @@ -3071,20 +1981,11 @@ pub struct PatternMatchClass { pub kwd_patterns: Vec, } -impl Node for PatternMatchClass { - const NAME: &'static str = "MatchClass"; - const FIELD_NAMES: &'static [&'static str] = &["cls", "patterns", "kwd_attrs", "kwd_patterns"]; -} impl From for Pattern { fn from(payload: PatternMatchClass) -> Self { Pattern::MatchClass(payload) } } -impl From for Ast { - fn from(payload: PatternMatchClass) -> Self { - Pattern::from(payload).into() - } -} /// See also [MatchStar](https://docs.python.org/3/library/ast.html#ast.MatchStar) #[derive(Clone, Debug, PartialEq)] @@ -3093,20 +1994,11 @@ pub struct PatternMatchStar { pub name: Option, } -impl Node for PatternMatchStar { - const NAME: &'static str = "MatchStar"; - const FIELD_NAMES: &'static [&'static str] = &["name"]; -} impl From for Pattern { fn from(payload: PatternMatchStar) -> Self { Pattern::MatchStar(payload) } } -impl From for Ast { - fn from(payload: PatternMatchStar) -> Self { - Pattern::from(payload).into() - } -} /// See also [MatchAs](https://docs.python.org/3/library/ast.html#ast.MatchAs) #[derive(Clone, Debug, PartialEq)] @@ -3116,20 +2008,11 @@ pub struct PatternMatchAs { pub name: Option, } -impl Node for PatternMatchAs { - const NAME: &'static str = "MatchAs"; - const FIELD_NAMES: &'static [&'static str] = &["pattern", "name"]; -} impl From for Pattern { fn from(payload: PatternMatchAs) -> Self { Pattern::MatchAs(payload) } } -impl From for Ast { - fn from(payload: PatternMatchAs) -> Self { - Pattern::from(payload).into() - } -} /// See also [MatchOr](https://docs.python.org/3/library/ast.html#ast.MatchOr) #[derive(Clone, Debug, PartialEq)] @@ -3138,25 +2021,11 @@ pub struct PatternMatchOr { pub patterns: Vec, } -impl Node for PatternMatchOr { - const NAME: &'static str = "MatchOr"; - const FIELD_NAMES: &'static [&'static str] = &["patterns"]; -} impl From for Pattern { fn from(payload: PatternMatchOr) -> Self { Pattern::MatchOr(payload) } } -impl From for Ast { - fn from(payload: PatternMatchOr) -> Self { - Pattern::from(payload).into() - } -} - -impl Node for Pattern { - const NAME: &'static str = "pattern"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} /// See also [type_ignore](https://docs.python.org/3/library/ast.html#ast.type_ignore) #[derive(Clone, Debug, PartialEq, is_macro::Is)] @@ -3172,25 +2041,11 @@ pub struct TypeIgnoreTypeIgnore { pub tag: String, } -impl Node for TypeIgnoreTypeIgnore { - const NAME: &'static str = "TypeIgnore"; - const FIELD_NAMES: &'static [&'static str] = &["lineno", "tag"]; -} impl From for TypeIgnore { fn from(payload: TypeIgnoreTypeIgnore) -> Self { TypeIgnore::TypeIgnore(payload) } } -impl From for Ast { - fn from(payload: TypeIgnoreTypeIgnore) -> Self { - TypeIgnore::from(payload).into() - } -} - -impl Node for TypeIgnore { - const NAME: &'static str = "type_ignore"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} /// See also [type_param](https://docs.python.org/3/library/ast.html#ast.type_param) #[derive(Clone, Debug, PartialEq, is_macro::Is)] @@ -3208,20 +2063,11 @@ pub struct TypeParamTypeVar { pub bound: Option>, } -impl Node for TypeParamTypeVar { - const NAME: &'static str = "TypeVar"; - const FIELD_NAMES: &'static [&'static str] = &["name", "bound"]; -} impl From for TypeParam { fn from(payload: TypeParamTypeVar) -> Self { TypeParam::TypeVar(payload) } } -impl From for Ast { - fn from(payload: TypeParamTypeVar) -> Self { - TypeParam::from(payload).into() - } -} /// See also [ParamSpec](https://docs.python.org/3/library/ast.html#ast.ParamSpec) #[derive(Clone, Debug, PartialEq)] @@ -3230,20 +2076,11 @@ pub struct TypeParamParamSpec { pub name: Identifier, } -impl Node for TypeParamParamSpec { - const NAME: &'static str = "ParamSpec"; - const FIELD_NAMES: &'static [&'static str] = &["name"]; -} impl From for TypeParam { fn from(payload: TypeParamParamSpec) -> Self { TypeParam::ParamSpec(payload) } } -impl From for Ast { - fn from(payload: TypeParamParamSpec) -> Self { - TypeParam::from(payload).into() - } -} /// See also [TypeVarTuple](https://docs.python.org/3/library/ast.html#ast.TypeVarTuple) #[derive(Clone, Debug, PartialEq)] @@ -3252,25 +2089,11 @@ pub struct TypeParamTypeVarTuple { pub name: Identifier, } -impl Node for TypeParamTypeVarTuple { - const NAME: &'static str = "TypeVarTuple"; - const FIELD_NAMES: &'static [&'static str] = &["name"]; -} impl From for TypeParam { fn from(payload: TypeParamTypeVarTuple) -> Self { TypeParam::TypeVarTuple(payload) } } -impl From for Ast { - fn from(payload: TypeParamTypeVarTuple) -> Self { - TypeParam::from(payload).into() - } -} - -impl Node for TypeParam { - const NAME: &'static str = "type_param"; - const FIELD_NAMES: &'static [&'static str] = &[]; -} /// See also [decorator](https://docs.python.org/3/library/ast.html#ast.decorator) #[derive(Clone, Debug, PartialEq)] @@ -3279,12 +2102,7 @@ pub struct Decorator { pub expression: Expr, } -impl Node for Decorator { - const NAME: &'static str = "decorator"; - const FIELD_NAMES: &'static [&'static str] = &["expression"]; -} - -/// An alternative type of AST `arguments`. This is parser-friendly and human-friendly definition of function arguments. +/// An alternative type of AST `arguments`. This is ruff_python_parser-friendly and human-friendly definition of function arguments. /// This form also has advantage to implement pre-order traverse. /// `defaults` and `kw_defaults` fields are removed and the default values are placed under each `arg_with_default` typed argument. /// `vararg` and `kwarg` are still typed as `arg` because they never can have a default value. @@ -3304,12 +2122,6 @@ pub struct Arguments { pub kwarg: Option>, } -impl Node for Arguments { - const NAME: &'static str = "alt:arguments"; - const FIELD_NAMES: &'static [&'static str] = - &["posonlyargs", "args", "vararg", "kwonlyargs", "kwarg"]; -} - /// An alternative type of AST `arg`. This is used for each function argument that might have a default value. /// Used by `Arguments` original type. /// @@ -3322,11 +2134,6 @@ pub struct ArgWithDefault { pub default: Option>, } -impl Node for ArgWithDefault { - const NAME: &'static str = "arg_with_default"; - const FIELD_NAMES: &'static [&'static str] = &["def", "default"]; -} - pub type Suite = Vec; impl CmpOp { @@ -3497,3 +2304,733 @@ impl MagicKind { len.into() } } + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Identifier { + id: String, + range: TextRange, +} + +impl Identifier { + #[inline] + pub fn new(id: impl Into, range: TextRange) -> Self { + Self { + id: id.into(), + range, + } + } +} + +impl Identifier { + #[inline] + pub fn as_str(&self) -> &str { + self.id.as_str() + } +} + +impl PartialEq for Identifier { + #[inline] + fn eq(&self, other: &str) -> bool { + self.id == other + } +} + +impl PartialEq for Identifier { + #[inline] + fn eq(&self, other: &String) -> bool { + &self.id == other + } +} + +impl std::ops::Deref for Identifier { + type Target = str; + #[inline] + fn deref(&self) -> &Self::Target { + self.id.as_str() + } +} + +impl AsRef for Identifier { + #[inline] + fn as_ref(&self) -> &str { + self.id.as_str() + } +} + +impl AsRef for Identifier { + #[inline] + fn as_ref(&self) -> &String { + &self.id + } +} + +impl std::fmt::Display for Identifier { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.id, f) + } +} + +impl From for String { + #[inline] + fn from(identifier: Identifier) -> String { + identifier.id + } +} + +impl Ranged for Identifier { + fn range(&self) -> TextRange { + self.range + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Int(u32); + +impl Int { + pub fn new(i: u32) -> Self { + Self(i) + } + pub fn to_u32(&self) -> u32 { + self.0 + } + pub fn to_usize(&self) -> usize { + self.0 as _ + } +} + +impl std::cmp::PartialEq for Int { + #[inline] + fn eq(&self, other: &u32) -> bool { + self.0 == *other + } +} + +impl std::cmp::PartialEq for Int { + #[inline] + fn eq(&self, other: &usize) -> bool { + self.0 as usize == *other + } +} + +#[derive(Clone, Debug, PartialEq, is_macro::Is)] +pub enum Constant { + None, + Bool(bool), + Str(String), + Bytes(Vec), + Int(BigInt), + Float(f64), + Complex { real: f64, imag: f64 }, + Ellipsis, +} + +impl Constant { + pub fn is_true(self) -> bool { + self.bool().map_or(false, |b| b) + } + pub fn is_false(self) -> bool { + self.bool().map_or(false, |b| !b) + } + pub fn complex(self) -> Option<(f64, f64)> { + match self { + Constant::Complex { real, imag } => Some((real, imag)), + _ => None, + } + } +} + +impl From for Constant { + fn from(s: String) -> Constant { + Self::Str(s) + } +} +impl From> for Constant { + fn from(b: Vec) -> Constant { + Self::Bytes(b) + } +} +impl From for Constant { + fn from(b: bool) -> Constant { + Self::Bool(b) + } +} +impl From for Constant { + fn from(i: BigInt) -> Constant { + Self::Int(i) + } +} + +#[cfg(feature = "rustpython-literal")] +impl std::fmt::Display for Constant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Constant::None => f.pad("None"), + Constant::Bool(b) => f.pad(if *b { "True" } else { "False" }), + Constant::Str(s) => rustpython_literal::escape::UnicodeEscape::new_repr(s.as_str()) + .str_repr() + .write(f), + Constant::Bytes(b) => { + let escape = rustpython_literal::escape::AsciiEscape::new_repr(b); + let repr = escape.bytes_repr().to_string().unwrap(); + f.pad(&repr) + } + Constant::Int(i) => std::fmt::Display::fmt(&i, f), + Constant::Float(fp) => f.pad(&rustpython_literal::float::to_string(*fp)), + Constant::Complex { real, imag } => { + if *real == 0.0 { + write!(f, "{imag}j") + } else { + write!(f, "({real}{imag:+}j)") + } + } + Constant::Ellipsis => f.pad("..."), + } + } +} + +impl Ranged for crate::nodes::ModModule { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ModInteractive { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ModExpression { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ModFunctionType { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::Mod { + fn range(&self) -> TextRange { + match self { + Self::Module(node) => node.range(), + Self::Interactive(node) => node.range(), + Self::Expression(node) => node.range(), + Self::FunctionType(node) => node.range(), + } + } +} + +impl Ranged for crate::nodes::StmtFunctionDef { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtAsyncFunctionDef { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtClassDef { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtReturn { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtDelete { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtTypeAlias { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtAssign { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtAugAssign { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtAnnAssign { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtFor { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtAsyncFor { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtWhile { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtIf { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ElifElseClause { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtWith { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtAsyncWith { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtMatch { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtRaise { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtTry { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtTryStar { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtAssert { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtImport { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtImportFrom { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtGlobal { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtNonlocal { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtExpr { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtPass { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtBreak { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::StmtContinue { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for StmtLineMagic { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::Stmt { + fn range(&self) -> TextRange { + match self { + Self::FunctionDef(node) => node.range(), + Self::AsyncFunctionDef(node) => node.range(), + Self::ClassDef(node) => node.range(), + Self::Return(node) => node.range(), + Self::Delete(node) => node.range(), + Self::TypeAlias(node) => node.range(), + Self::Assign(node) => node.range(), + Self::AugAssign(node) => node.range(), + Self::AnnAssign(node) => node.range(), + Self::For(node) => node.range(), + Self::AsyncFor(node) => node.range(), + Self::While(node) => node.range(), + Self::If(node) => node.range(), + Self::With(node) => node.range(), + Self::AsyncWith(node) => node.range(), + Self::Match(node) => node.range(), + Self::Raise(node) => node.range(), + Self::Try(node) => node.range(), + Self::TryStar(node) => node.range(), + Self::Assert(node) => node.range(), + Self::Import(node) => node.range(), + Self::ImportFrom(node) => node.range(), + Self::Global(node) => node.range(), + Self::Nonlocal(node) => node.range(), + Self::Expr(node) => node.range(), + Self::Pass(node) => node.range(), + Self::Break(node) => node.range(), + Self::Continue(node) => node.range(), + Stmt::LineMagic(node) => node.range(), + } + } +} + +impl Ranged for crate::nodes::ExprBoolOp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprNamedExpr { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprBinOp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprUnaryOp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprLambda { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprIfExp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprDict { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprSet { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprListComp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprSetComp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprDictComp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprGeneratorExp { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprAwait { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprYield { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprYieldFrom { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprCompare { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprCall { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprFormattedValue { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprJoinedStr { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprConstant { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprAttribute { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprSubscript { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprStarred { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprName { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprList { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprTuple { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExprSlice { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for ExprLineMagic { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::Expr { + fn range(&self) -> TextRange { + match self { + Self::BoolOp(node) => node.range(), + Self::NamedExpr(node) => node.range(), + Self::BinOp(node) => node.range(), + Self::UnaryOp(node) => node.range(), + Self::Lambda(node) => node.range(), + Self::IfExp(node) => node.range(), + Self::Dict(node) => node.range(), + Self::Set(node) => node.range(), + Self::ListComp(node) => node.range(), + Self::SetComp(node) => node.range(), + Self::DictComp(node) => node.range(), + Self::GeneratorExp(node) => node.range(), + Self::Await(node) => node.range(), + Self::Yield(node) => node.range(), + Self::YieldFrom(node) => node.range(), + Self::Compare(node) => node.range(), + Self::Call(node) => node.range(), + Self::FormattedValue(node) => node.range(), + Self::JoinedStr(node) => node.range(), + Self::Constant(node) => node.range(), + Self::Attribute(node) => node.range(), + Self::Subscript(node) => node.range(), + Self::Starred(node) => node.range(), + Self::Name(node) => node.range(), + Self::List(node) => node.range(), + Self::Tuple(node) => node.range(), + Self::Slice(node) => node.range(), + Expr::LineMagic(node) => node.range(), + } + } +} + +impl Ranged for crate::nodes::Comprehension { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ExceptHandlerExceptHandler { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::ExceptHandler { + fn range(&self) -> TextRange { + match self { + Self::ExceptHandler(node) => node.range(), + } + } +} + +impl Ranged for crate::nodes::PythonArguments { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::Arg { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::Keyword { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::Alias { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::WithItem { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::MatchCase { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchValue { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchSingleton { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchSequence { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchMapping { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchClass { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchStar { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchAs { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::PatternMatchOr { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::Pattern { + fn range(&self) -> TextRange { + match self { + Self::MatchValue(node) => node.range(), + Self::MatchSingleton(node) => node.range(), + Self::MatchSequence(node) => node.range(), + Self::MatchMapping(node) => node.range(), + Self::MatchClass(node) => node.range(), + Self::MatchStar(node) => node.range(), + Self::MatchAs(node) => node.range(), + Self::MatchOr(node) => node.range(), + } + } +} + +impl Ranged for crate::nodes::TypeIgnoreTypeIgnore { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::TypeIgnore { + fn range(&self) -> TextRange { + match self { + Self::TypeIgnore(node) => node.range(), + } + } +} +impl Ranged for crate::nodes::TypeParamTypeVar { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::TypeParamTypeVarTuple { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::TypeParamParamSpec { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::TypeParam { + fn range(&self) -> TextRange { + match self { + Self::TypeVar(node) => node.range(), + Self::TypeVarTuple(node) => node.range(), + Self::ParamSpec(node) => node.range(), + } + } +} +impl Ranged for crate::nodes::Decorator { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::Arguments { + fn range(&self) -> TextRange { + self.range + } +} +impl Ranged for crate::nodes::ArgWithDefault { + fn range(&self) -> TextRange { + self.range + } +} diff --git a/parser/Cargo.toml b/ruff_python_parser/Cargo.toml similarity index 76% rename from parser/Cargo.toml rename to ruff_python_parser/Cargo.toml index 129db9f8..b3769c7e 100644 --- a/parser/Cargo.toml +++ b/ruff_python_parser/Cargo.toml @@ -1,15 +1,14 @@ [package] -name = "rustpython-parser" +name = "ruff_python_parser" version = "0.2.0" description = "Parser for python code." -authors = ["RustPython Team"] +authors = ["Charlie Marsh ", "RustPython Team"] build = "build.rs" -repository = "https://github.com/RustPython/Parser/" license = "MIT" edition = "2021" [features] -serde = ["dep:serde", "rustpython-parser-core/serde"] +serde = ["dep:serde"] [build-dependencies] anyhow = { workspace = true } @@ -17,8 +16,8 @@ lalrpop = { version = "0.20.0", default-features = false, optional = true } tiny-keccak = { version = "2", features = ["sha3"] } [dependencies] -rustpython-ast = { workspace = true } -rustpython-parser-core = { workspace = true } +ruff_python_ast = { workspace = true } +ruff_text_size = { workspace = true } itertools = { workspace = true } is-macro = { workspace = true } diff --git a/parser/README.md b/ruff_python_parser/README.md similarity index 100% rename from parser/README.md rename to ruff_python_parser/README.md diff --git a/parser/build.rs b/ruff_python_parser/build.rs similarity index 94% rename from parser/build.rs rename to ruff_python_parser/build.rs index a9bc3832..fb6d4b4d 100644 --- a/parser/build.rs +++ b/ruff_python_parser/build.rs @@ -19,7 +19,7 @@ fn main() -> anyhow::Result<()> { #[cfg(not(feature = "lalrpop"))] { target = PathBuf::from("src/python.rs"); - error = "python.lalrpop and src/python.rs doesn't match. This is a rustpython-parser bug. Please report it unless you are editing rustpython-parser. Run `lalrpop src/python.lalrpop` to build parser again."; + error = "python.lalrpop and src/python.rs doesn't match. This is a rustpython-ruff_python_parser bug. Please report it unless you are editing rustpython-ruff_python_parser. Run `lalrpop src/python.lalrpop` to build ruff_python_parser again."; } let Some(message) = requires_lalrpop(SOURCE, &target) else { diff --git a/parser/src/context.rs b/ruff_python_parser/src/context.rs similarity index 100% rename from parser/src/context.rs rename to ruff_python_parser/src/context.rs diff --git a/parser/src/function.rs b/ruff_python_parser/src/function.rs similarity index 99% rename from parser/src/function.rs rename to ruff_python_parser/src/function.rs index 1f8215ec..f81dc82c 100644 --- a/parser/src/function.rs +++ b/ruff_python_parser/src/function.rs @@ -1,13 +1,12 @@ // Contains functions that perform validation and parsing of arguments and parameters. // Checks apply both to functions and to lambdas. -use crate::text_size::TextRange; use crate::{ ast, lexer::{LexicalError, LexicalErrorType}, - text_size::TextSize, }; +use ruff_python_ast::Ranged; +use ruff_text_size::{TextRange, TextSize}; use rustc_hash::FxHashSet; -use rustpython_ast::Ranged; pub(crate) struct ArgumentList { pub(crate) args: Vec, diff --git a/parser/src/gen/parse.rs b/ruff_python_parser/src/gen/parse.rs similarity index 100% rename from parser/src/gen/parse.rs rename to ruff_python_parser/src/gen/parse.rs diff --git a/parser/src/lexer.rs b/ruff_python_parser/src/lexer.rs similarity index 99% rename from parser/src/lexer.rs rename to ruff_python_parser/src/lexer.rs index 2df4d498..0645ac3d 100644 --- a/parser/src/lexer.rs +++ b/ruff_python_parser/src/lexer.rs @@ -12,7 +12,7 @@ //! # Example //! //! ``` -//! use rustpython_parser::{lexer::lex, Tok, Mode, StringKind}; +//! use ruff_python_parser::{lexer::lex, Tok, Mode, StringKind}; //! //! let source = "x = 'RustPython'"; //! let tokens = lex(source, Mode::Module) @@ -34,17 +34,16 @@ use std::{char, cmp::Ordering, str::FromStr}; use num_bigint::BigInt; use num_traits::{Num, Zero}; -use rustpython_ast::MagicKind; +use ruff_python_ast::MagicKind; +use ruff_text_size::{TextLen, TextRange, TextSize}; use unic_emoji_char::is_emoji_presentation; use unic_ucd_ident::{is_xid_continue, is_xid_start}; use crate::lexer::cursor::{Cursor, EOF_CHAR}; use crate::lexer::indentation::{Indentation, Indentations}; -use crate::text_size::TextLen; use crate::{ soft_keywords::SoftKeywordTransformer, string::FStringErrorType, - text_size::{TextRange, TextSize}, token::{StringKind, Tok}, Mode, }; @@ -78,7 +77,7 @@ pub type LexResult = Result; /// # Examples /// /// ``` -/// use rustpython_parser::{Mode, lexer::lex}; +/// use ruff_python_parser::{Mode, lexer::lex}; /// /// let source = "def hello(): return 'world'"; /// let lexer = lex(source, Mode::Module); @@ -1119,7 +1118,7 @@ fn is_identifier_continuation(c: char) -> bool { #[cfg(test)] mod tests { use num_bigint::BigInt; - use rustpython_ast::MagicKind; + use ruff_python_ast::MagicKind; use super::*; diff --git a/parser/src/lexer/cursor.rs b/ruff_python_parser/src/lexer/cursor.rs similarity index 98% rename from parser/src/lexer/cursor.rs rename to ruff_python_parser/src/lexer/cursor.rs index ff1f3b74..2811c1ab 100644 --- a/parser/src/lexer/cursor.rs +++ b/ruff_python_parser/src/lexer/cursor.rs @@ -1,4 +1,4 @@ -use crate::text_size::{TextLen, TextSize}; +use ruff_text_size::{TextLen, TextSize}; use std::str::Chars; pub(crate) const EOF_CHAR: char = '\0'; diff --git a/parser/src/lexer/indentation.rs b/ruff_python_parser/src/lexer/indentation.rs similarity index 100% rename from parser/src/lexer/indentation.rs rename to ruff_python_parser/src/lexer/indentation.rs diff --git a/parser/src/lib.rs b/ruff_python_parser/src/lib.rs similarity index 53% rename from parser/src/lib.rs rename to ruff_python_parser/src/lib.rs index 5b56e54a..df4abb93 100644 --- a/parser/src/lib.rs +++ b/ruff_python_parser/src/lib.rs @@ -15,16 +15,16 @@ //! Name("print"), LeftParen, String("Hello world"), RightParen //! ``` //! -//! these tokens are then consumed by the parser, which matches them against a set of +//! these tokens are then consumed by the ruff_python_parser, which matches them against a set of //! grammar rules to verify that the source code is syntactically valid and to construct //! an AST that represents the source code. //! -//! During parsing, the parser consumes the tokens generated by the lexer and constructs +//! During parsing, the ruff_python_parser consumes the tokens generated by the lexer and constructs //! a tree representation of the source code. The tree is made up of nodes that represent //! the different syntactic constructs of the language. If the source code is syntactically //! invalid, parsing fails and an error is returned. After a successful parse, the AST can //! be used to perform further analysis on the source code. Continuing with the example -//! above, the AST generated by the parser would _roughly_ look something like this: +//! above, the AST generated by the ruff_python_parser would _roughly_ look something like this: //! //! ```text //! node: Expr { @@ -48,7 +48,7 @@ //! }, //!``` //! -//! Note: The Tokens/ASTs shown above are not the exact tokens/ASTs generated by the parser. +//! Note: The Tokens/ASTs shown above are not the exact tokens/ASTs generated by the ruff_python_parser. //! //! ## Source code layout: //! @@ -56,16 +56,16 @@ //! //! - token: This module contains the definition of the tokens that are generated by the lexer. //! - [lexer]: This module contains the lexer and is responsible for generating the tokens. -//! - parser: This module contains an interface to the parser and is responsible for generating the AST. +//! - ruff_python_parser: This module contains an interface to the ruff_python_parser and is responsible for generating the AST. //! - Functions and strings have special parsing requirements that are handled in additional files. -//! - mode: This module contains the definition of the different modes that the parser can be in. +//! - mode: This module contains the definition of the different modes that the ruff_python_parser can be in. //! //! # Examples //! //! For example, to get a stream of tokens from a given string, one could do this: //! //! ``` -//! use rustpython_parser::{lexer::lex, Mode}; +//! use ruff_python_parser::{lexer::lex, Mode}; //! //! let python_source = r#" //! def is_odd(i): @@ -75,10 +75,10 @@ //! assert!(tokens.all(|t| t.is_ok())); //! ``` //! -//! These tokens can be directly fed into the parser to generate an AST: +//! These tokens can be directly fed into the ruff_python_parser to generate an AST: //! //! ``` -//! use rustpython_parser::{lexer::lex, Mode, parse_tokens}; +//! use ruff_python_parser::{lexer::lex, Mode, parse_tokens}; //! //! let python_source = r#" //! def is_odd(i): @@ -94,7 +94,7 @@ //! mode or tokenizing the source beforehand: //! //! ``` -//! use rustpython_parser::{Parse, ast}; +//! use ruff_python_parser::{Parse, ast}; //! //! let python_source = r#" //! def is_odd(i): @@ -109,14 +109,15 @@ //! [parsing]: https://en.wikipedia.org/wiki/Parsing //! [lexer]: crate::lexer -#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/main/logo.png")] -#![doc(html_root_url = "https://docs.rs/rustpython-parser/")] - -pub use rustpython_ast as ast; -pub use rustpython_parser_core::{text_size, Mode}; +pub use parser::{parse, parse_starts_at, parse_tokens, Parse, ParseError, ParseErrorType}; +#[allow(deprecated)] +pub use parser::{parse_expression, parse_expression_starts_at, parse_program}; +pub use ruff_python_ast as ast; +pub use string::FStringErrorType; +pub use token::{StringKind, Tok}; mod function; -// Skip flattening lexer to distinguish from full parser +// Skip flattening lexer to distinguish from full ruff_python_parser mod context; pub mod lexer; mod parser; @@ -124,12 +125,63 @@ mod soft_keywords; mod string; mod token; -pub use parser::{parse, parse_starts_at, parse_tokens, Parse, ParseError, ParseErrorType}; -pub use string::FStringErrorType; -pub use token::{StringKind, Tok}; +/// Control in the different modes by which a source file can be parsed. +/// The mode argument specifies in what way code must be parsed. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Mode { + /// The code consists of a sequence of statements. + Module, + /// The code consists of a sequence of interactive statement. + Interactive, + /// The code consists of a single expression. + Expression, + /// The code consists of a sequence of statements which are part of a + /// Jupyter Notebook and thus could include escape commands scoped to + /// 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: + /// + /// - [Magic command system] which is limited to [line magics] and can start + /// with `?` or `??`. + /// - [Dynamic object information] which can start with `?` or `??`. + /// - [System shell access] which can start with `!` or `!!`. + /// - [Automatic parentheses and quotes] which can start with `/`, `;`, or `,`. + /// + /// [Magic command system]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#magic-command-system + /// [line magics]: https://ipython.readthedocs.io/en/stable/interactive/magics.html#line-magics + /// [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 + /// [Automatic parentheses and quotes]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#automatic-parentheses-and-quotes + Jupyter, +} -#[allow(deprecated)] -pub use parser::{parse_expression, parse_expression_starts_at, parse_program}; +impl std::str::FromStr for Mode { + type Err = ModeParseError; + fn from_str(s: &str) -> Result { + match s { + "exec" | "single" => Ok(Mode::Module), + "eval" => Ok(Mode::Expression), + "jupyter" => Ok(Mode::Jupyter), + _ => Err(ModeParseError), + } + } +} + +/// Returned when a given mode is not valid. +#[derive(Debug)] +pub struct ModeParseError; + +impl std::fmt::Display for ModeParseError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, r#"mode must be "exec", "eval", "jupyter", or "single""#) + } +} #[rustfmt::skip] mod python { diff --git a/parser/src/parser.rs b/ruff_python_parser/src/parser.rs similarity index 95% rename from parser/src/parser.rs rename to ruff_python_parser/src/parser.rs index b2675f96..fc153cff 100644 --- a/parser/src/parser.rs +++ b/ruff_python_parser/src/parser.rs @@ -1,4 +1,4 @@ -//! Contains the interface to the Python parser. +//! Contains the interface to the Python ruff_python_parser. //! //! Functions in this module can be used to parse Python code into an [Abstract Syntax Tree] //! (AST) that is then transformed into bytecode. @@ -12,17 +12,17 @@ //! [Abstract Syntax Tree]: https://en.wikipedia.org/wiki/Abstract_syntax_tree //! [`Mode`]: crate::mode -use std::iter; +use std::{fmt, iter}; use itertools::Itertools; pub(super) use lalrpop_util::ParseError as LalrpopError; +use ruff_text_size::TextSize; use crate::lexer::{lex, lex_starts_at}; use crate::{ ast::{self, Ranged}, lexer::{self, LexResult, LexicalError, LexicalErrorType}, python, - text_size::TextSize, token::Tok, Mode, }; @@ -34,7 +34,7 @@ use crate::{ /// For example, parsing a simple function definition and a call to that function: /// /// ``` -/// use rustpython_parser::{self as parser, ast, Parse}; +/// use ruff_python_parser::{self as parser, ast, Parse}; /// let source = r#" /// def foo(): /// return 42 @@ -49,7 +49,8 @@ use crate::{ /// somewhat silly, location: /// /// ``` -/// use rustpython_parser::{self as parser, ast, Parse, text_size::TextSize}; +/// # use ruff_text_size::TextSize; +/// # use ruff_python_parser::{self as parser, ast, Parse}; /// /// let expr = ast::Expr::parse_starts_at("1 + 2", "", TextSize::from(400)); /// assert!(expr.is_ok()); @@ -228,7 +229,7 @@ impl Parse for ast::Constant { /// For example, parsing a simple function definition and a call to that function: /// /// ``` -/// use rustpython_parser as parser; +/// use ruff_python_parser as parser; /// let source = r#" /// def foo(): /// return 42 @@ -238,7 +239,7 @@ impl Parse for ast::Constant { /// let program = parser::parse_program(source, ""); /// assert!(program.is_ok()); /// ``` -#[deprecated = "Use ast::Suite::parse from rustpython_parser::Parse trait."] +#[deprecated = "Use ruff_python_ast::Suite::parse from rustpython_parser::Parse trait."] pub fn parse_program(source: &str, source_path: &str) -> Result { parse(source, Mode::Module, source_path).map(|top| match top { ast::Mod::Module(ast::ModModule { body, .. }) => body, @@ -256,13 +257,13 @@ pub fn parse_program(source: &str, source_path: &str) -> Result"); /// /// assert!(expr.is_ok()); /// /// ``` -#[deprecated = "Use ast::Expr::parse from rustpython_parser::Parse trait."] +#[deprecated = "Use ruff_python_ast::Expr::parse from rustpython_parser::Parse trait."] pub fn parse_expression(source: &str, path: &str) -> Result { ast::Expr::parse(source, path) } @@ -278,12 +279,13 @@ pub fn parse_expression(source: &str, path: &str) -> Result", TextSize::from(400)); /// assert!(expr.is_ok()); /// ``` -#[deprecated = "Use ast::Expr::parse_starts_at from rustpython_parser::Parse trait."] +#[deprecated = "Use ruff_python_ast::Expr::parse_starts_at from rustpython_parser::Parse trait."] pub fn parse_expression_starts_at( source: &str, path: &str, @@ -304,7 +306,7 @@ pub fn parse_expression_starts_at( /// parsing: /// /// ``` -/// use rustpython_parser::{Mode, parse}; +/// use ruff_python_parser::{Mode, parse}; /// /// let expr = parse("1 + 2", Mode::Expression, ""); /// assert!(expr.is_ok()); @@ -313,7 +315,7 @@ pub fn parse_expression_starts_at( /// Alternatively, we can parse a full Python program consisting of multiple lines: /// /// ``` -/// use rustpython_parser::{Mode, parse}; +/// use ruff_python_parser::{Mode, parse}; /// /// let source = r#" /// class Greeter: @@ -328,7 +330,7 @@ pub fn parse_expression_starts_at( /// Additionally, we can parse a Python program containing Jupyter magics: /// /// ``` -/// use rustpython_parser::{Mode, parse}; +/// use ruff_python_parser::{Mode, parse}; /// /// let source = r#" /// %timeit 1 + 2 @@ -350,7 +352,8 @@ pub fn parse(source: &str, mode: Mode, source_path: &str) -> Result"); /// assert!(expr.is_ok()); @@ -422,7 +425,44 @@ fn parse_filtered_tokens( /// Represents represent errors that occur during parsing and are /// returned by the `parse_*` functions. -pub type ParseError = rustpython_parser_core::BaseError; + +#[derive(Debug, PartialEq)] +pub struct ParseError { + pub error: ParseErrorType, + pub offset: TextSize, + pub source_path: String, +} + +impl std::ops::Deref for ParseError { + type Target = ParseErrorType; + + fn deref(&self) -> &Self::Target { + &self.error + } +} + +impl std::error::Error for ParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&self.error) + } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!( + f, + "{} at byte offset {}", + &self.error, + u32::from(self.offset) + ) + } +} + +impl ParseError { + pub fn error(self) -> ParseErrorType { + self.error + } +} /// Represents the different types of errors that can occur during parsing. #[derive(Debug, PartialEq)] diff --git a/parser/src/python.lalrpop b/ruff_python_parser/src/python.lalrpop similarity index 99% rename from parser/src/python.lalrpop rename to ruff_python_parser/src/python.lalrpop index 68796dcc..f149d8de 100644 --- a/parser/src/python.lalrpop +++ b/ruff_python_parser/src/python.lalrpop @@ -4,6 +4,7 @@ // See also: https://greentreesnakes.readthedocs.io/en/latest/nodes.html#keyword use num_bigint::BigInt; +use ruff_text_size::TextSize; use crate::{ ast::{self as ast, Ranged, MagicKind}, Mode, @@ -12,7 +13,6 @@ use crate::{ context::set_context, string::parse_strings, token::{self, StringKind}, - text_size::TextSize }; grammar(mode: Mode); diff --git a/parser/src/python.rs b/ruff_python_parser/src/python.rs similarity index 99% rename from parser/src/python.rs rename to ruff_python_parser/src/python.rs index b0906d1a..44566054 100644 --- a/parser/src/python.rs +++ b/ruff_python_parser/src/python.rs @@ -1,6 +1,7 @@ // auto-generated: "lalrpop 0.20.0" -// sha3: 263bb187f0a83dfe2a024fa0eed0ad8cb855da5991584b5040fa7d870fdb84af +// sha3: 44f1432ea449af8f70398fcbc3e641e2fd720734693a493e635795dd681954e0 use num_bigint::BigInt; +use ruff_text_size::TextSize; use crate::{ ast::{self as ast, Ranged, MagicKind}, Mode, @@ -9,7 +10,6 @@ use crate::{ context::set_context, string::parse_strings, token::{self, StringKind}, - text_size::TextSize }; #[allow(unused_extern_crates)] extern crate lalrpop_util as __lalrpop_util; @@ -23,6 +23,7 @@ extern crate alloc; mod __parse__Top { use num_bigint::BigInt; + use ruff_text_size::TextSize; use crate::{ ast::{self as ast, Ranged, MagicKind}, Mode, @@ -31,7 +32,6 @@ mod __parse__Top { context::set_context, string::parse_strings, token::{self, StringKind}, - text_size::TextSize }; #[allow(unused_extern_crates)] extern crate lalrpop_util as __lalrpop_util; diff --git a/parser/src/snapshots/rustpython_parser__context__tests__ann_assign_name.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__ann_assign_name.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__context__tests__ann_assign_name.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__ann_assign_name.snap index a9fef6a4..f40642c4 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__ann_assign_name.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__ann_assign_name.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_attribute.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_attribute.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_attribute.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_attribute.snap index 93d0ad00..42e29002 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_attribute.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_attribute.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_for.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_for.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_for.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_for.snap index d3779056..46e74927 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_for.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_for.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_list.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_list.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_list.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_list.snap index cda4cd3f..50b82e8d 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_list.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_list.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_list_comp.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_list_comp.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_list_comp.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_list_comp.snap index dabec649..c9da3630 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_list_comp.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_list_comp.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_name.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_name.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_name.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_name.snap index 2e347778..444de811 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_name.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_name.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_named_expr.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_named_expr.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_named_expr.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_named_expr.snap index 20afb057..b71b4f78 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_named_expr.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_named_expr.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_set_comp.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_set_comp.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_set_comp.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_set_comp.snap index 16a9521b..b22c3ba3 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_set_comp.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_set_comp.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_starred.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_starred.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_starred.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_starred.snap index 23ff1aad..821d4794 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_starred.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_starred.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_subscript.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_subscript.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_subscript.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_subscript.snap index cf21a8a7..aebd4869 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_subscript.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_subscript.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_tuple.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_tuple.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_tuple.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_tuple.snap index ed3a180d..24fa08aa 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_tuple.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_tuple.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__assign_with.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_with.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__context__tests__assign_with.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_with.snap index c0133d6f..c93bd9a6 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__assign_with.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__assign_with.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__aug_assign_attribute.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_attribute.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__context__tests__aug_assign_attribute.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_attribute.snap index c27f6287..e1718457 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__aug_assign_attribute.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_attribute.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__aug_assign_name.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_name.snap similarity index 93% rename from parser/src/snapshots/rustpython_parser__context__tests__aug_assign_name.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_name.snap index 3c1740ac..a27baed9 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__aug_assign_name.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_name.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__aug_assign_subscript.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_subscript.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__context__tests__aug_assign_subscript.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_subscript.snap index 6c3c819c..f377ad1c 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__aug_assign_subscript.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__aug_assign_subscript.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__del_attribute.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_attribute.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__context__tests__del_attribute.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_attribute.snap index 99dcc867..4bfd6392 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__del_attribute.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_attribute.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__del_name.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_name.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__context__tests__del_name.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_name.snap index 7f215028..e1122917 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__del_name.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_name.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__context__tests__del_subscript.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_subscript.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__context__tests__del_subscript.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_subscript.snap index a863f42b..dcf82ea7 100644 --- a/parser/src/snapshots/rustpython_parser__context__tests__del_subscript.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__context__tests__del_subscript.snap @@ -1,5 +1,5 @@ --- -source: parser/src/context.rs +source: ruff_python_parser/src/context.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_kw_only_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__function_kw_only_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args.snap index f1455fbd..3b88bf43 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_kw_only_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_kw_only_args_with_defaults.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args_with_defaults.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__function_kw_only_args_with_defaults.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args_with_defaults.snap index 76f2fa80..cd701b90 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_kw_only_args_with_defaults.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_kw_only_args_with_defaults.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_no_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__function__tests__function_no_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args.snap index ced8c5c6..25bea2a8 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_no_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_no_args_with_ranges.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args_with_ranges.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__function__tests__function_no_args_with_ranges.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args_with_ranges.snap index ced8c5c6..25bea2a8 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_no_args_with_ranges.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_no_args_with_ranges.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args.snap index fbac8111..448fcbe9 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap index a65fa4df..90c013ad 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap index 8164ff55..036be2eb 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap index d32593a8..bffe0a7a 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_and_kw_only_args_with_defaults_and_varargs_and_kwargs.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__function_pos_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args.snap index a62524c1..781b623a 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_args_with_defaults.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_defaults.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__function_pos_args_with_defaults.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_defaults.snap index 7e1fb357..94aeb846 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_args_with_defaults.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_defaults.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_args_with_ranges.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_ranges.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__function_pos_args_with_ranges.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_ranges.snap index a62524c1..781b623a 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__function_pos_args_with_ranges.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__function_pos_args_with_ranges.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__lambda_kw_only_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__lambda_kw_only_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args.snap index f7fc7605..e1d40c73 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__lambda_kw_only_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__lambda_kw_only_args_with_defaults.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args_with_defaults.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__lambda_kw_only_args_with_defaults.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args_with_defaults.snap index bf0d45ab..e69e0ba4 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__lambda_kw_only_args_with_defaults.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_kw_only_args_with_defaults.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__lambda_no_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_no_args.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__function__tests__lambda_no_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_no_args.snap index ff2b3c71..dfa2b957 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__lambda_no_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_no_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_and_kw_only_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_and_kw_only_args.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_and_kw_only_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_and_kw_only_args.snap index 3ed7fdcf..756ae05a 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_and_kw_only_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_and_kw_only_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args.snap index 4e9797f7..84448b67 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_args_with_defaults.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args_with_defaults.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_args_with_defaults.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args_with_defaults.snap index 4d302b30..705fbfdb 100644 --- a/parser/src/snapshots/rustpython_parser__function__tests__lambda_pos_args_with_defaults.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__function__tests__lambda_pos_args_with_defaults.snap @@ -1,5 +1,5 @@ --- -source: parser/src/function.rs +source: ruff_python_parser/src/function.rs expression: parse_ast --- Ok( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__decorator_ranges.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__decorator_ranges.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__parser__tests__decorator_ranges.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__decorator_ranges.snap index 14202fb2..6f78e11c 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__decorator_ranges.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__decorator_ranges.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__dict_unpacking.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__dict_unpacking.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__parser__tests__dict_unpacking.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__dict_unpacking.snap index 2a6d4329..9bf5d790 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__dict_unpacking.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__dict_unpacking.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- Dict( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__generator_expression_argument.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__generator_expression_argument.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__generator_expression_argument.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__generator_expression_argument.snap index a94344b0..a44b5a28 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__generator_expression_argument.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__generator_expression_argument.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- Call( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__jupyter_magic.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__jupyter_magic.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__jupyter_magic.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__jupyter_magic.snap index db972dd3..33774995 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__jupyter_magic.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__jupyter_magic.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- Module( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__match.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__match.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match.snap index 0de5d0df..4b70e283 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__match.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__match_as_identifier.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match_as_identifier.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__match_as_identifier.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match_as_identifier.snap index 4a87847c..67b80457 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__match_as_identifier.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__match_as_identifier.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__numeric_literals.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__numeric_literals.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals.snap index 3ad53568..00043014 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__numeric_literals.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__numeric_literals_attribute_access.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals_attribute_access.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__numeric_literals_attribute_access.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals_attribute_access.snap index a5f419b4..8bbcb62a 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__numeric_literals_attribute_access.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__numeric_literals_attribute_access.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_bool_op_and.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_bool_op_and.snap similarity index 92% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_bool_op_and.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_bool_op_and.snap index 139ee40a..23a2f028 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_bool_op_and.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_bool_op_and.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- BoolOp( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_bool_op_or.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_bool_op_or.snap similarity index 92% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_bool_op_or.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_bool_op_or.snap index 71c1e95a..9dd2064d 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_bool_op_or.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_bool_op_or.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- BoolOp( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_class.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_class.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class.snap index 35f022b3..fd19901b 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_class.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_class_generic_types.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class_generic_types.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_class_generic_types.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class_generic_types.snap index 672b6230..3fe4da48 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_class_generic_types.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_class_generic_types.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_dict_comprehension.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_dict_comprehension.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_dict_comprehension.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_dict_comprehension.snap index 69d3ae78..71516505 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_dict_comprehension.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_dict_comprehension.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- DictComp( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_double_list_comprehension.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_double_list_comprehension.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_double_list_comprehension.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_double_list_comprehension.snap index 3f381687..ea0f128b 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_double_list_comprehension.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_double_list_comprehension.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- ListComp( diff --git a/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_empty.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_empty.snap new file mode 100644 index 00000000..ebbdbabe --- /dev/null +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_empty.snap @@ -0,0 +1,5 @@ +--- +source: ruff_python_parser/src/parser.rs +expression: parse_ast +--- +[] diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_f_string.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_f_string.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_f_string.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_f_string.snap index 0d72dcdd..61d2e7f0 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_f_string.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_f_string.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_function_definition.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_function_definition.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_function_definition.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_function_definition.snap index f84851f8..d86a299b 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_function_definition.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_function_definition.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_generator_comprehension.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_generator_comprehension.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_generator_comprehension.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_generator_comprehension.snap index f9bede46..3e52a96a 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_generator_comprehension.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_generator_comprehension.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- GeneratorExp( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_if_elif_else.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_if_elif_else.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_if_elif_else.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_if_elif_else.snap index 1b285173..884965d5 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_if_elif_else.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_if_elif_else.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_if_else_generator_comprehension.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_if_else_generator_comprehension.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_if_else_generator_comprehension.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_if_else_generator_comprehension.snap index 9d8e9d2e..d77377ef 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_if_else_generator_comprehension.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_if_else_generator_comprehension.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- GeneratorExp( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_kwargs.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_kwargs.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_kwargs.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_kwargs.snap index 29854553..c27f089b 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_kwargs.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_kwargs.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_lambda.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_lambda.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda.snap index 4797c541..8d591288 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_lambda.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_lambda_no_args.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda_no_args.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_lambda_no_args.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda_no_args.snap index beb32bd5..83bf7cd5 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_lambda_no_args.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_lambda_no_args.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_list_comprehension.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_list_comprehension.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_list_comprehension.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_list_comprehension.snap index 2b7560f2..200ff6a4 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_list_comprehension.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_list_comprehension.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- ListComp( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_named_expression_generator_comprehension.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_named_expression_generator_comprehension.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_named_expression_generator_comprehension.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_named_expression_generator_comprehension.snap index d603f5e6..a5c8c136 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_named_expression_generator_comprehension.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_named_expression_generator_comprehension.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- GeneratorExp( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_print_2.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_2.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_print_2.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_2.snap index 46376e27..ac80602c 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_print_2.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_2.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_print_hello.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_hello.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_print_hello.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_hello.snap index 4c55021c..0a8551d7 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_print_hello.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_print_hello.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_string.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_string.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_string.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_string.snap index ab4a4537..d9d8d198 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_string.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_string.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_tuples.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_tuples.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_tuples.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_tuples.snap index 55b03e4d..fe381035 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_tuples.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_tuples.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_type_declaration.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_type_declaration.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__parse_type_declaration.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_type_declaration.snap index a4fbb740..3e3ed242 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_type_declaration.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__parse_type_declaration.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__patma.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__patma.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__patma.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__patma.snap index 04b97fe9..95d90ec5 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__patma.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__patma.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__slice.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__slice.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__parser__tests__slice.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__slice.snap index f994344c..f2d665d4 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__slice.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__slice.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- Subscript( diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__star_index.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__star_index.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__star_index.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__star_index.snap index 24ccff88..cb2b1da1 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__star_index.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__star_index.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__try.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__try.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try.snap index 8b0b71d0..29a4fc32 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__try.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__try_star.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try_star.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__try_star.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try_star.snap index 4bbeafff..a075d61d 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__try_star.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__try_star.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__type_as_identifier.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__type_as_identifier.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__type_as_identifier.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__type_as_identifier.snap index 64436f23..973b87c9 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__type_as_identifier.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__type_as_identifier.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__variadic_generics.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__variadic_generics.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__parser__tests__variadic_generics.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__variadic_generics.snap index 7e9a09f9..1ccf7c69 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__variadic_generics.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__variadic_generics.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__with_statement.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__with_statement.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__parser__tests__with_statement.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__with_statement.snap index 5530e674..661d2d4e 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__with_statement.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__parser__tests__with_statement.snap @@ -1,5 +1,5 @@ --- -source: parser/src/parser.rs +source: ruff_python_parser/src/parser.rs expression: "ast::Suite::parse(source, \"\").unwrap()" --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__backspace_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__backspace_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap index 2b010efa..272bf3ca 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__backspace_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__backspace_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__bell_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__bell_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap index 8ea0075e..085f2f73 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__bell_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__bell_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__carriage_return_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__carriage_return_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap index 133911b9..b5e6c7f7 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__carriage_return_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__carriage_return_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__character_tabulation_with_justification_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__character_tabulation_with_justification_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap index 49d820ac..d52c67c4 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__character_tabulation_with_justification_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__character_tabulation_with_justification_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__delete_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__delete_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap index 7aaa0249..9d06a373 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__delete_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__delete_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__double_quoted_byte.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__string__tests__double_quoted_byte.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap index 79ef9ba6..2becaa21 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__double_quoted_byte.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__double_quoted_byte.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__escape_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__escape_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap index 45ed6b34..ff14ada2 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__escape_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__escape_char_in_byte_literal.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__escape_char_in_byte_literal.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap index d1898ba2..6b0616a6 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__escape_char_in_byte_literal.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_char_in_byte_literal.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__escape_octet.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap similarity index 92% rename from parser/src/snapshots/rustpython_parser__string__tests__escape_octet.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap index dfb9c9a6..31ca5396 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__escape_octet.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__escape_octet.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__form_feed_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__form_feed_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap index 9dbbc7f5..1b5ff95c 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__form_feed_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__form_feed_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_constant_range.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap similarity index 98% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_constant_range.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap index fd948684..728d74e8 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_constant_range.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_constant_range.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_escaped_character.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_escaped_character.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap index 18a0f192..4f819107 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_escaped_character.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_character.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_escaped_newline.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_escaped_newline.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap index 472507b6..9039af29 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_escaped_newline.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_escaped_newline.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_line_continuation.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_line_continuation.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap index f9286876..d9186147 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_line_continuation.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_line_continuation.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_base.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_base.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap index 9fdcc7be..c1ad0496 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_base.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_base_more.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_base_more.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap index 91cf8126..d38489eb 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_base_more.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_base_more.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_format.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_format.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap index 18d0d2df..7b58156f 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_parse_self_documenting_format.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_parse_self_documenting_format.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__fstring_unescaped_newline.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__fstring_unescaped_newline.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap index 0190a3e6..a153231e 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__fstring_unescaped_newline.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__fstring_unescaped_newline.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__hts_alias.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__hts_alias.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap index bcba9195..ebb2f043 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__hts_alias.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__hts_alias.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_empty_fstring.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_fstring.snap similarity index 56% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_empty_fstring.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_fstring.snap index 94515b97..37f4e0d9 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_empty_fstring.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_empty_fstring.snap @@ -1,5 +1,5 @@ --- -source: compiler/parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: "parse_fstring(\"\").unwrap()" --- [] diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_1.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_1.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap index 0925a623..246247d9 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_1.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_1.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_2.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_2.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap index 0925a623..246247d9 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_2.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_2.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_3.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap similarity index 97% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_3.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap index ab7f507b..cc973598 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_f_string_concat_3.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_f_string_concat_3.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap index 2af0e247..df1c2b08 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_equals.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_equals.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_equals.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_equals.snap index e1834fe8..4d85a2e9 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_equals.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_equals.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_nested_spec.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_nested_spec.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap index fdfffcad..6c400606 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_nested_spec.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_nested_spec.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_not_equals.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_equals.snap similarity index 96% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_not_equals.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_equals.snap index 432f87d4..e2ff0044 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_not_equals.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_equals.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_not_nested_spec.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_not_nested_spec.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap index bbecd705..d7975271 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_not_nested_spec.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_not_nested_spec.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_self_doc_prec_space.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_self_doc_prec_space.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap index 5a290d1e..a8d23864 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_self_doc_prec_space.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_prec_space.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_self_doc_trailing_space.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_self_doc_trailing_space.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap index 53d66931..4c4b1d0f 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_self_doc_trailing_space.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_self_doc_trailing_space.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_yield_expr.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_yield_expr.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_yield_expr.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_yield_expr.snap index 0b9ed9ca..2b062948 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_fstring_yield_expr.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_fstring_yield_expr.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_string_concat.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_string_concat.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap index 6429c7d8..5bc99cc8 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_string_concat.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_concat.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_string_triple_quotes_with_kind.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap similarity index 91% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_string_triple_quotes_with_kind.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap index a6b2822f..da62ff38 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_string_triple_quotes_with_kind.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_string_triple_quotes_with_kind.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_f_string_concat_1.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_u_f_string_concat_1.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap index b8a3ab87..5f76b944 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_f_string_concat_1.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_1.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_f_string_concat_2.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap similarity index 94% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_u_f_string_concat_2.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap index 8bed0e1e..447d75ef 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_f_string_concat_2.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_f_string_concat_2.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_string_concat_1.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap similarity index 89% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_u_string_concat_1.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap index bd730d81..d52df9b3 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_string_concat_1.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_1.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_string_concat_2.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap similarity index 90% rename from parser/src/snapshots/rustpython_parser__string__tests__parse_u_string_concat_2.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap index 8be87509..6b6265b7 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__parse_u_string_concat_2.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__parse_u_string_concat_2.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__raw_byte_literal_1.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap similarity index 92% rename from parser/src/snapshots/rustpython_parser__string__tests__raw_byte_literal_1.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap index decb6ece..faa48589 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__raw_byte_literal_1.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_1.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__raw_byte_literal_2.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap similarity index 91% rename from parser/src/snapshots/rustpython_parser__string__tests__raw_byte_literal_2.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap index 4972fc0d..e28e7c79 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__raw_byte_literal_2.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_byte_literal_2.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__raw_fstring.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__string__tests__raw_fstring.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap index 9b52d7c7..6e067fa6 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__raw_fstring.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__raw_fstring.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__single_quoted_byte.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap similarity index 99% rename from parser/src/snapshots/rustpython_parser__string__tests__single_quoted_byte.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap index 79ef9ba6..2becaa21 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__single_quoted_byte.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__single_quoted_byte.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/snapshots/rustpython_parser__string__tests__triple_quoted_raw_fstring.snap b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap similarity index 95% rename from parser/src/snapshots/rustpython_parser__string__tests__triple_quoted_raw_fstring.snap rename to ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap index 9e2db104..d7e888df 100644 --- a/parser/src/snapshots/rustpython_parser__string__tests__triple_quoted_raw_fstring.snap +++ b/ruff_python_parser/src/snapshots/ruff_python_parser__string__tests__triple_quoted_raw_fstring.snap @@ -1,5 +1,5 @@ --- -source: parser/src/string.rs +source: ruff_python_parser/src/string.rs expression: parse_ast --- [ diff --git a/parser/src/soft_keywords.rs b/ruff_python_parser/src/soft_keywords.rs similarity index 98% rename from parser/src/soft_keywords.rs rename to ruff_python_parser/src/soft_keywords.rs index 51278a46..778925fe 100644 --- a/parser/src/soft_keywords.rs +++ b/ruff_python_parser/src/soft_keywords.rs @@ -15,7 +15,7 @@ use itertools::{Itertools, MultiPeek}; /// soft keyword tokens with `identifier` tokens if they are used as identifiers. /// /// Handling soft keywords in this intermediary pass allows us to simplify both the lexer and -/// parser, as neither of them need to be aware of soft keywords. +/// ruff_python_parser, as neither of them need to be aware of soft keywords. pub struct SoftKeywordTransformer where I: Iterator, diff --git a/parser/src/string.rs b/ruff_python_parser/src/string.rs similarity index 99% rename from parser/src/string.rs rename to ruff_python_parser/src/string.rs index ea711e96..58b46dbd 100644 --- a/parser/src/string.rs +++ b/ruff_python_parser/src/string.rs @@ -1,9 +1,8 @@ // Contains the logic for parsing string literals (mostly concerned with f-strings.) // // The lexer doesn't do any special handling of f-strings, it just treats them as -// regular strings. Since the parser has no definition of f-string formats (Pending PEP 701) +// regular strings. Since the ruff_python_parser has no definition of f-string formats (Pending PEP 701) // we have to do the parsing here, manually. -use crate::text_size::TextRange; use crate::{ ast::{self, Constant, Expr}, lexer::{LexicalError, LexicalErrorType}, @@ -11,11 +10,8 @@ use crate::{ token::{StringKind, Tok}, }; use itertools::Itertools; -use rustpython_ast::Ranged; -use rustpython_parser_core::{ - text_size::{TextLen, TextSize}, - ConversionFlag, -}; +use ruff_python_ast::{ConversionFlag, Ranged}; +use ruff_text_size::{TextLen, TextRange, TextSize}; // unicode_name2 does not expose `MAX_NAME_LENGTH`, so we replicate that constant here, fix #3798 const MAX_UNICODE_NAME: usize = 88; diff --git a/parser/src/token.rs b/ruff_python_parser/src/token.rs similarity index 99% rename from parser/src/token.rs rename to ruff_python_parser/src/token.rs index 86a86686..4dfc7456 100644 --- a/parser/src/token.rs +++ b/ruff_python_parser/src/token.rs @@ -1,12 +1,13 @@ -//! Token type for Python source code created by the lexer and consumed by the parser. +//! Token type for Python source code created by the lexer and consumed by the ruff_python_parser. //! //! This module defines the tokens that the lexer recognizes. The tokens are //! loosely based on the token definitions found in the [CPython source]. //! //! [CPython source]: https://github.com/python/cpython/blob/dfc2e065a2e71011017077e549cd2f9bf4944c54/Include/internal/pycore_token.h; use crate::ast::MagicKind; -use crate::{text_size::TextSize, Mode}; +use crate::Mode; use num_bigint::BigInt; +use ruff_text_size::TextSize; use std::fmt; /// The set of tokens the Python source code can be tokenized in.