mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-23 04:55:09 +00:00
Use shared leading_quote
implementation in ruff_python_formatter (#3396)
This commit is contained in:
parent
dfe1cad928
commit
ff2c0dd491
21 changed files with 114 additions and 123 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2154,6 +2154,7 @@ dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ruff_formatter",
|
"ruff_formatter",
|
||||||
|
"ruff_python_ast",
|
||||||
"ruff_python_stdlib",
|
"ruff_python_stdlib",
|
||||||
"ruff_rustpython",
|
"ruff_rustpython",
|
||||||
"ruff_testing_macros",
|
"ruff_testing_macros",
|
||||||
|
|
|
@ -27,7 +27,7 @@ use ruff_python_ast::types::{
|
||||||
use ruff_python_ast::typing::{match_annotated_subscript, Callable, SubscriptKind};
|
use ruff_python_ast::typing::{match_annotated_subscript, Callable, SubscriptKind};
|
||||||
use ruff_python_ast::visitor::{walk_excepthandler, walk_pattern, Visitor};
|
use ruff_python_ast::visitor::{walk_excepthandler, walk_pattern, Visitor};
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
branch_detection, cast, helpers, operations, strings, typing, visibility, visitor,
|
branch_detection, cast, helpers, operations, str, typing, visibility, visitor,
|
||||||
};
|
};
|
||||||
use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS};
|
use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS};
|
||||||
use ruff_python_stdlib::path::is_python_stub_file;
|
use ruff_python_stdlib::path::is_python_stub_file;
|
||||||
|
@ -5292,7 +5292,7 @@ impl<'a> Checker<'a> {
|
||||||
Location::new(expr.location.row(), expr.location.column()),
|
Location::new(expr.location.row(), expr.location.column()),
|
||||||
));
|
));
|
||||||
|
|
||||||
let body = strings::raw_contents(contents);
|
let body = str::raw_contents(contents);
|
||||||
let docstring = Docstring {
|
let docstring = Docstring {
|
||||||
kind: definition.kind,
|
kind: definition.kind,
|
||||||
expr,
|
expr,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::leading_quote;
|
use ruff_python_ast::str::leading_quote;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::leading_quote;
|
use ruff_python_ast::str::leading_quote;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::leading_quote;
|
use ruff_python_ast::str::{is_triple_quote, leading_quote};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::whitespace::LinesWithTrailingNewline;
|
use ruff_python_ast::whitespace::LinesWithTrailingNewline;
|
||||||
use ruff_python_stdlib::str::TRIPLE_QUOTE_PREFIXES;
|
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||||
|
@ -54,7 +53,7 @@ pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if TRIPLE_QUOTE_PREFIXES.contains(&first_line) {
|
if is_triple_quote(first_line) {
|
||||||
if checker
|
if checker
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::leading_quote;
|
use ruff_python_ast::str::leading_quote;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::whitespace::LinesWithTrailingNewline;
|
use ruff_python_ast::whitespace::LinesWithTrailingNewline;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::{leading_quote, trailing_quote};
|
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::whitespace::LinesWithTrailingNewline;
|
use ruff_python_ast::whitespace::LinesWithTrailingNewline;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustpython_parser::ast::{Excepthandler, Expr};
|
||||||
use rustpython_parser::{lexer, Mode, Tok};
|
use rustpython_parser::{lexer, Mode, Tok};
|
||||||
|
|
||||||
use ruff_python_ast::source_code::{Locator, Stylist};
|
use ruff_python_ast::source_code::{Locator, Stylist};
|
||||||
use ruff_python_ast::strings::raw_contents;
|
use ruff_python_ast::str::raw_contents;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
|
||||||
use crate::cst::matchers::{match_expr, match_module};
|
use crate::cst::matchers::{match_expr, match_module};
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Location, Operator};
|
||||||
use rustpython_parser::{lexer, Mode, Tok};
|
use rustpython_parser::{lexer, Mode, Tok};
|
||||||
|
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::{leading_quote, trailing_quote};
|
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, KeywordData};
|
||||||
use rustpython_parser::{lexer, Mode, Tok};
|
use rustpython_parser::{lexer, Mode, Tok};
|
||||||
|
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::{leading_quote, trailing_quote};
|
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Location};
|
||||||
use rustpython_parser::{lexer, Mode, Tok};
|
use rustpython_parser::{lexer, Mode, Tok};
|
||||||
|
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::strings::{leading_quote, trailing_quote};
|
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::whitespace::indentation;
|
use ruff_python_ast::whitespace::indentation;
|
||||||
use ruff_python_stdlib::identifiers::is_identifier;
|
use ruff_python_stdlib::identifiers::is_identifier;
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub mod logging;
|
||||||
pub mod operations;
|
pub mod operations;
|
||||||
pub mod relocate;
|
pub mod relocate;
|
||||||
pub mod source_code;
|
pub mod source_code;
|
||||||
pub mod strings;
|
pub mod str;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod typing;
|
pub mod typing;
|
||||||
pub mod visibility;
|
pub mod visibility;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustpython_parser::{lexer, Mode, Tok};
|
||||||
use crate::source_code::Locator;
|
use crate::source_code::Locator;
|
||||||
use ruff_rustpython::vendor;
|
use ruff_rustpython::vendor;
|
||||||
|
|
||||||
use crate::strings::leading_quote;
|
use crate::str::leading_quote;
|
||||||
use crate::types::Range;
|
use crate::types::Range;
|
||||||
|
|
||||||
pub struct Stylist<'a> {
|
pub struct Stylist<'a> {
|
||||||
|
|
97
crates/ruff_python_ast/src/str.rs
Normal file
97
crates/ruff_python_ast/src/str.rs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/// See: <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>
|
||||||
|
const TRIPLE_QUOTE_STR_PREFIXES: &[&str] = &[
|
||||||
|
"u\"\"\"", "u'''", "r\"\"\"", "r'''", "U\"\"\"", "U'''", "R\"\"\"", "R'''", "\"\"\"", "'''",
|
||||||
|
];
|
||||||
|
const SINGLE_QUOTE_STR_PREFIXES: &[&str] = &[
|
||||||
|
"u\"", "u'", "r\"", "r'", "U\"", "U'", "R\"", "R'", "\"", "'",
|
||||||
|
];
|
||||||
|
pub const TRIPLE_QUOTE_BYTE_PREFIXES: &[&str] = &[
|
||||||
|
"br'''", "rb'''", "bR'''", "Rb'''", "Br'''", "rB'''", "RB'''", "BR'''", "b'''", "br\"\"\"",
|
||||||
|
"rb\"\"\"", "bR\"\"\"", "Rb\"\"\"", "Br\"\"\"", "rB\"\"\"", "RB\"\"\"", "BR\"\"\"", "b\"\"\"",
|
||||||
|
"B\"\"\"",
|
||||||
|
];
|
||||||
|
pub const SINGLE_QUOTE_BYTE_PREFIXES: &[&str] = &[
|
||||||
|
"br'", "rb'", "bR'", "Rb'", "Br'", "rB'", "RB'", "BR'", "b'", "br\"", "rb\"", "bR\"", "Rb\"",
|
||||||
|
"Br\"", "rB\"", "RB\"", "BR\"", "b\"", "B\"",
|
||||||
|
];
|
||||||
|
const TRIPLE_QUOTE_SUFFIXES: &[&str] = &["\"\"\"", "'''"];
|
||||||
|
const SINGLE_QUOTE_SUFFIXES: &[&str] = &["\"", "'"];
|
||||||
|
|
||||||
|
/// Strip the leading and trailing quotes from a docstring.
|
||||||
|
pub fn raw_contents(contents: &str) -> &str {
|
||||||
|
for pattern in TRIPLE_QUOTE_STR_PREFIXES
|
||||||
|
.iter()
|
||||||
|
.chain(TRIPLE_QUOTE_BYTE_PREFIXES)
|
||||||
|
{
|
||||||
|
if contents.starts_with(pattern) {
|
||||||
|
return &contents[pattern.len()..contents.len() - 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for pattern in SINGLE_QUOTE_STR_PREFIXES
|
||||||
|
.iter()
|
||||||
|
.chain(SINGLE_QUOTE_BYTE_PREFIXES)
|
||||||
|
{
|
||||||
|
if contents.starts_with(pattern) {
|
||||||
|
return &contents[pattern.len()..contents.len() - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unreachable!("Expected docstring to start with a valid triple- or single-quote prefix")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the leading quote for a string or byte literal (e.g., `"""`).
|
||||||
|
pub fn leading_quote(content: &str) -> Option<&str> {
|
||||||
|
if let Some(first_line) = content.lines().next() {
|
||||||
|
for pattern in TRIPLE_QUOTE_STR_PREFIXES
|
||||||
|
.iter()
|
||||||
|
.chain(TRIPLE_QUOTE_BYTE_PREFIXES)
|
||||||
|
.chain(SINGLE_QUOTE_STR_PREFIXES)
|
||||||
|
.chain(SINGLE_QUOTE_BYTE_PREFIXES)
|
||||||
|
{
|
||||||
|
if first_line.starts_with(pattern) {
|
||||||
|
return Some(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the trailing quote string for a string or byte literal (e.g., `"""`).
|
||||||
|
pub fn trailing_quote(content: &str) -> Option<&&str> {
|
||||||
|
TRIPLE_QUOTE_SUFFIXES
|
||||||
|
.iter()
|
||||||
|
.chain(SINGLE_QUOTE_SUFFIXES)
|
||||||
|
.find(|&pattern| content.ends_with(pattern))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the string is a triple-quote string or byte prefix.
|
||||||
|
pub fn is_triple_quote(content: &str) -> bool {
|
||||||
|
TRIPLE_QUOTE_STR_PREFIXES.contains(&content) || TRIPLE_QUOTE_BYTE_PREFIXES.contains(&content)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{
|
||||||
|
SINGLE_QUOTE_BYTE_PREFIXES, SINGLE_QUOTE_STR_PREFIXES, TRIPLE_QUOTE_BYTE_PREFIXES,
|
||||||
|
TRIPLE_QUOTE_STR_PREFIXES,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_prefixes() {
|
||||||
|
let prefixes = TRIPLE_QUOTE_STR_PREFIXES
|
||||||
|
.iter()
|
||||||
|
.chain(TRIPLE_QUOTE_BYTE_PREFIXES)
|
||||||
|
.chain(SINGLE_QUOTE_STR_PREFIXES)
|
||||||
|
.chain(SINGLE_QUOTE_BYTE_PREFIXES)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
for (i, prefix_i) in prefixes.iter().enumerate() {
|
||||||
|
for (j, prefix_j) in prefixes.iter().enumerate() {
|
||||||
|
if i > j {
|
||||||
|
assert!(
|
||||||
|
!prefix_i.starts_with(*prefix_j),
|
||||||
|
"Prefixes are not unique: {prefix_i} starts with {prefix_j}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,38 +0,0 @@
|
||||||
use ruff_python_stdlib::str::{
|
|
||||||
SINGLE_QUOTE_PREFIXES, SINGLE_QUOTE_SUFFIXES, TRIPLE_QUOTE_PREFIXES, TRIPLE_QUOTE_SUFFIXES,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Strip the leading and trailing quotes from a docstring.
|
|
||||||
pub fn raw_contents(contents: &str) -> &str {
|
|
||||||
for pattern in TRIPLE_QUOTE_PREFIXES {
|
|
||||||
if contents.starts_with(pattern) {
|
|
||||||
return &contents[pattern.len()..contents.len() - 3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for pattern in SINGLE_QUOTE_PREFIXES {
|
|
||||||
if contents.starts_with(pattern) {
|
|
||||||
return &contents[pattern.len()..contents.len() - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unreachable!("Expected docstring to start with a valid triple- or single-quote prefix")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the leading quote string for a docstring (e.g., `"""`).
|
|
||||||
pub fn leading_quote(content: &str) -> Option<&str> {
|
|
||||||
if let Some(first_line) = content.lines().next() {
|
|
||||||
for pattern in TRIPLE_QUOTE_PREFIXES.iter().chain(SINGLE_QUOTE_PREFIXES) {
|
|
||||||
if first_line.starts_with(pattern) {
|
|
||||||
return Some(pattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the trailing quote string for a docstring (e.g., `"""`).
|
|
||||||
pub fn trailing_quote(content: &str) -> Option<&&str> {
|
|
||||||
TRIPLE_QUOTE_SUFFIXES
|
|
||||||
.iter()
|
|
||||||
.chain(SINGLE_QUOTE_SUFFIXES)
|
|
||||||
.find(|&pattern| content.ends_with(pattern))
|
|
||||||
}
|
|
|
@ -7,6 +7,7 @@ rust-version = { workspace = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ruff_formatter = { path = "../ruff_formatter" }
|
ruff_formatter = { path = "../ruff_formatter" }
|
||||||
|
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||||
ruff_text_size = { path = "../ruff_text_size" }
|
ruff_text_size = { path = "../ruff_text_size" }
|
||||||
|
|
|
@ -3,31 +3,6 @@ use rustpython_parser::ast::Location;
|
||||||
use crate::core::locator::Locator;
|
use crate::core::locator::Locator;
|
||||||
use crate::core::types::Range;
|
use crate::core::types::Range;
|
||||||
|
|
||||||
/// Return the leading quote for a string or byte literal (e.g., `"""`).
|
|
||||||
pub fn leading_quote(content: &str) -> Option<&str> {
|
|
||||||
if let Some(first_line) = content.lines().next() {
|
|
||||||
for pattern in ruff_python_stdlib::str::TRIPLE_QUOTE_PREFIXES
|
|
||||||
.iter()
|
|
||||||
.chain(ruff_python_stdlib::bytes::TRIPLE_QUOTE_PREFIXES)
|
|
||||||
.chain(ruff_python_stdlib::str::SINGLE_QUOTE_PREFIXES)
|
|
||||||
.chain(ruff_python_stdlib::bytes::SINGLE_QUOTE_PREFIXES)
|
|
||||||
{
|
|
||||||
if first_line.starts_with(pattern) {
|
|
||||||
return Some(pattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the trailing quote string for a string or byte literal (e.g., `"""`).
|
|
||||||
pub fn trailing_quote(content: &str) -> Option<&&str> {
|
|
||||||
ruff_python_stdlib::str::TRIPLE_QUOTE_SUFFIXES
|
|
||||||
.iter()
|
|
||||||
.chain(ruff_python_stdlib::str::SINGLE_QUOTE_SUFFIXES)
|
|
||||||
.find(|&pattern| content.ends_with(pattern))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if the given string is a radix literal (e.g., `0b101`).
|
/// Return `true` if the given string is a radix literal (e.g., `0b101`).
|
||||||
pub fn is_radix_literal(content: &str) -> bool {
|
pub fn is_radix_literal(content: &str) -> bool {
|
||||||
content.starts_with("0b")
|
content.starts_with("0b")
|
||||||
|
@ -155,30 +130,3 @@ pub fn is_elif(orelse: &[rustpython_parser::ast::Stmt], locator: &Locator) -> bo
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn test_prefixes() {
|
|
||||||
let prefixes = ruff_python_stdlib::str::TRIPLE_QUOTE_PREFIXES
|
|
||||||
.iter()
|
|
||||||
.chain(ruff_python_stdlib::bytes::TRIPLE_QUOTE_PREFIXES)
|
|
||||||
.chain(ruff_python_stdlib::str::SINGLE_QUOTE_PREFIXES)
|
|
||||||
.chain(ruff_python_stdlib::bytes::SINGLE_QUOTE_PREFIXES)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
for i in 1..prefixes.len() {
|
|
||||||
for j in 0..i - 1 {
|
|
||||||
if i != j {
|
|
||||||
if prefixes[i].starts_with(prefixes[j]) {
|
|
||||||
assert!(
|
|
||||||
!prefixes[i].starts_with(prefixes[j]),
|
|
||||||
"Prefixes are not unique: {} starts with {}",
|
|
||||||
prefixes[i],
|
|
||||||
prefixes[j]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,10 +2,10 @@ use rustpython_parser::{Mode, Tok};
|
||||||
|
|
||||||
use ruff_formatter::prelude::*;
|
use ruff_formatter::prelude::*;
|
||||||
use ruff_formatter::{write, Format};
|
use ruff_formatter::{write, Format};
|
||||||
|
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||||
use ruff_text_size::TextSize;
|
use ruff_text_size::TextSize;
|
||||||
|
|
||||||
use crate::context::ASTFormatContext;
|
use crate::context::ASTFormatContext;
|
||||||
use crate::core::helpers::{leading_quote, trailing_quote};
|
|
||||||
use crate::core::types::Range;
|
use crate::core::types::Range;
|
||||||
use crate::cst::Expr;
|
use crate::cst::Expr;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
/// See: <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>
|
|
||||||
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
|
|
||||||
"br'''", "rb'''", "bR'''", "Rb'''", "Br'''", "rB'''", "RB'''", "BR'''", "b'''", "br\"\"\"",
|
|
||||||
"rb\"\"\"", "bR\"\"\"", "Rb\"\"\"", "Br\"\"\"", "rB\"\"\"", "RB\"\"\"", "BR\"\"\"", "b\"\"\"",
|
|
||||||
"B\"\"\"",
|
|
||||||
];
|
|
||||||
pub const SINGLE_QUOTE_PREFIXES: &[&str] = &[
|
|
||||||
"br'", "rb'", "bR'", "Rb'", "Br'", "rB'", "RB'", "BR'", "b'", "br\"", "rb\"", "bR\"", "Rb\"",
|
|
||||||
"Br\"", "rB\"", "RB\"", "BR\"", "b\"", "B\"",
|
|
||||||
];
|
|
|
@ -1,5 +1,4 @@
|
||||||
pub mod builtins;
|
pub mod builtins;
|
||||||
pub mod bytes;
|
|
||||||
pub mod future;
|
pub mod future;
|
||||||
pub mod identifiers;
|
pub mod identifiers;
|
||||||
pub mod keyword;
|
pub mod keyword;
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
/// See: <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>
|
/// See: <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>
|
||||||
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
|
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
|
||||||
"u\"\"\"", "u'''", "r\"\"\"", "r'''", "U\"\"\"", "U'''", "R\"\"\"", "R'''", "\"\"\"", "'''",
|
"u\"\"\"", "u'''", "r\"\"\"", "r'''", "U\"\"\"", "U'''", "R\"\"\"", "R'''", "\"\"\"", "'''",
|
||||||
|
@ -11,9 +8,6 @@ pub const SINGLE_QUOTE_PREFIXES: &[&str] = &[
|
||||||
pub const TRIPLE_QUOTE_SUFFIXES: &[&str] = &["\"\"\"", "'''"];
|
pub const TRIPLE_QUOTE_SUFFIXES: &[&str] = &["\"\"\"", "'''"];
|
||||||
pub const SINGLE_QUOTE_SUFFIXES: &[&str] = &["\"", "'"];
|
pub const SINGLE_QUOTE_SUFFIXES: &[&str] = &["\"", "'"];
|
||||||
|
|
||||||
pub static STRING_QUOTE_PREFIX_REGEX: Lazy<Regex> =
|
|
||||||
Lazy::new(|| Regex::new(r#"^(?i)[urb]*['"](?P<raw>.*)['"]$"#).unwrap());
|
|
||||||
|
|
||||||
pub fn is_lower(s: &str) -> bool {
|
pub fn is_lower(s: &str) -> bool {
|
||||||
let mut cased = false;
|
let mut cased = false;
|
||||||
for c in s.chars() {
|
for c in s.chars() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue