mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:24 +00:00
[flake8-simplify
] Fix raw string handling in SIM905
for embedded quotes (#19591)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
## Summary When splitting triple-quoted, raw strings one has to take care before attempting to make each item have single-quotes. Fixes #19577 --------- Co-authored-by: dylwil3 <dylwil3@gmail.com>
This commit is contained in:
parent
134435415e
commit
1a368b0bf9
3 changed files with 158 additions and 12 deletions
|
@ -130,3 +130,34 @@ print(" x ".rsplit(maxsplit=0))
|
||||||
print(" x ".rsplit(sep=None, maxsplit=0))
|
print(" x ".rsplit(sep=None, maxsplit=0))
|
||||||
print(" x ".rsplit(maxsplit=0))
|
print(" x ".rsplit(maxsplit=0))
|
||||||
print(" x ".rsplit(sep=None, maxsplit=0))
|
print(" x ".rsplit(sep=None, maxsplit=0))
|
||||||
|
|
||||||
|
# https://github.com/astral-sh/ruff/issues/19581 - embedded quotes in raw strings
|
||||||
|
r"""simple@example.com
|
||||||
|
very.common@example.com
|
||||||
|
FirstName.LastName@EasierReading.org
|
||||||
|
x@example.com
|
||||||
|
long.email-address-with-hyphens@and.subdomains.example.com
|
||||||
|
user.name+tag+sorting@example.com
|
||||||
|
name/surname@example.com
|
||||||
|
xample@s.example
|
||||||
|
" "@example.org
|
||||||
|
"john..doe"@example.org
|
||||||
|
mailhost!username@example.org
|
||||||
|
"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com
|
||||||
|
user%example.com@example.org
|
||||||
|
user-@example.org
|
||||||
|
I❤️CHOCOLATE@example.com
|
||||||
|
this\ still\"not\\allowed@example.com
|
||||||
|
stellyamburrr985@example.com
|
||||||
|
Abc.123@example.com
|
||||||
|
user+mailbox/department=shipping@example.com
|
||||||
|
!#$%&'*+-/=?^_`.{|}~@example.com
|
||||||
|
"Abc@def"@example.com
|
||||||
|
"Fred\ Bloggs"@example.com
|
||||||
|
"Joe.\\Blow"@example.com""".split("\n")
|
||||||
|
|
||||||
|
|
||||||
|
r"""first
|
||||||
|
'no need' to escape
|
||||||
|
"swap" quote style
|
||||||
|
"use' ugly triple quotes""".split("\n")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||||
|
use ruff_python_ast::StringFlags;
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
Expr, ExprCall, ExprContext, ExprList, ExprUnaryOp, StringLiteral, StringLiteralFlags,
|
Expr, ExprCall, ExprContext, ExprList, ExprUnaryOp, StringLiteral, StringLiteralFlags,
|
||||||
StringLiteralValue, UnaryOp, str::TripleQuotes,
|
StringLiteralValue, UnaryOp, str::TripleQuotes,
|
||||||
|
@ -116,26 +117,50 @@ pub(crate) fn split_static_string(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn replace_flags(elt: &str, flags: StringLiteralFlags) -> StringLiteralFlags {
|
||||||
|
// In the ideal case we can wrap the element in _single_ quotes of the same
|
||||||
|
// style. For example, both of these are okay:
|
||||||
|
//
|
||||||
|
// ```python
|
||||||
|
// """itemA
|
||||||
|
// itemB
|
||||||
|
// itemC""".split() # -> ["itemA", "itemB", "itemC"]
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// ```python
|
||||||
|
// r"""itemA
|
||||||
|
// 'single'quoted
|
||||||
|
// """.split() # -> [r"itemA",r"'single'quoted'"]
|
||||||
|
// ```
|
||||||
|
if !flags.prefix().is_raw() || !elt.contains(flags.quote_style().as_char()) {
|
||||||
|
flags.with_triple_quotes(TripleQuotes::No)
|
||||||
|
}
|
||||||
|
// If we have a raw string containing a quotation mark of the same style,
|
||||||
|
// then we have to swap the style of quotation marks used
|
||||||
|
else if !elt.contains(flags.quote_style().opposite().as_char()) {
|
||||||
|
flags
|
||||||
|
.with_quote_style(flags.quote_style().opposite())
|
||||||
|
.with_triple_quotes(TripleQuotes::No)
|
||||||
|
} else
|
||||||
|
// If both types of quotes are used in the raw, triple-quoted string, then
|
||||||
|
// we are forced to either add escapes or keep the triple quotes. We opt for
|
||||||
|
// the latter.
|
||||||
|
{
|
||||||
|
flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn construct_replacement(elts: &[&str], flags: StringLiteralFlags) -> Expr {
|
fn construct_replacement(elts: &[&str], flags: StringLiteralFlags) -> Expr {
|
||||||
Expr::List(ExprList {
|
Expr::List(ExprList {
|
||||||
elts: elts
|
elts: elts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|elt| {
|
.map(|elt| {
|
||||||
|
let element_flags = replace_flags(elt, flags);
|
||||||
Expr::from(StringLiteral {
|
Expr::from(StringLiteral {
|
||||||
value: Box::from(*elt),
|
value: Box::from(*elt),
|
||||||
range: TextRange::default(),
|
range: TextRange::default(),
|
||||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||||
// intentionally omit the triple quote flag, if set, to avoid strange
|
flags: element_flags,
|
||||||
// replacements like
|
|
||||||
//
|
|
||||||
// ```python
|
|
||||||
// """
|
|
||||||
// itemA
|
|
||||||
// itemB
|
|
||||||
// itemC
|
|
||||||
// """.split() # -> ["""itemA""", """itemB""", """itemC"""]
|
|
||||||
// ```
|
|
||||||
flags: flags.with_triple_quotes(TripleQuotes::No),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
|
@ -1226,6 +1226,7 @@ SIM905.py:130:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
130 |+print([" x"])
|
130 |+print([" x"])
|
||||||
131 131 | print(" x ".rsplit(maxsplit=0))
|
131 131 | print(" x ".rsplit(maxsplit=0))
|
||||||
132 132 | print(" x ".rsplit(sep=None, maxsplit=0))
|
132 132 | print(" x ".rsplit(sep=None, maxsplit=0))
|
||||||
|
133 133 |
|
||||||
|
|
||||||
SIM905.py:131:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
SIM905.py:131:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
|
|
|
|
||||||
|
@ -1244,6 +1245,8 @@ SIM905.py:131:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
131 |-print(" x ".rsplit(maxsplit=0))
|
131 |-print(" x ".rsplit(maxsplit=0))
|
||||||
131 |+print([" x"])
|
131 |+print([" x"])
|
||||||
132 132 | print(" x ".rsplit(sep=None, maxsplit=0))
|
132 132 | print(" x ".rsplit(sep=None, maxsplit=0))
|
||||||
|
133 133 |
|
||||||
|
134 134 | # https://github.com/astral-sh/ruff/issues/19581 - embedded quotes in raw strings
|
||||||
|
|
||||||
SIM905.py:132:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
SIM905.py:132:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
|
|
|
|
||||||
|
@ -1251,6 +1254,8 @@ SIM905.py:132:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
131 | print(" x ".rsplit(maxsplit=0))
|
131 | print(" x ".rsplit(maxsplit=0))
|
||||||
132 | print(" x ".rsplit(sep=None, maxsplit=0))
|
132 | print(" x ".rsplit(sep=None, maxsplit=0))
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM905
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM905
|
||||||
|
133 |
|
||||||
|
134 | # https://github.com/astral-sh/ruff/issues/19581 - embedded quotes in raw strings
|
||||||
|
|
|
|
||||||
= help: Replace with list literal
|
= help: Replace with list literal
|
||||||
|
|
||||||
|
@ -1260,3 +1265,88 @@ SIM905.py:132:7: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
131 131 | print(" x ".rsplit(maxsplit=0))
|
131 131 | print(" x ".rsplit(maxsplit=0))
|
||||||
132 |-print(" x ".rsplit(sep=None, maxsplit=0))
|
132 |-print(" x ".rsplit(sep=None, maxsplit=0))
|
||||||
132 |+print([" x"])
|
132 |+print([" x"])
|
||||||
|
133 133 |
|
||||||
|
134 134 | # https://github.com/astral-sh/ruff/issues/19581 - embedded quotes in raw strings
|
||||||
|
135 135 | r"""simple@example.com
|
||||||
|
|
||||||
|
SIM905.py:135:1: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
|
|
|
||||||
|
134 | # https://github.com/astral-sh/ruff/issues/19581 - embedded quotes in raw strings
|
||||||
|
135 | / r"""simple@example.com
|
||||||
|
136 | | very.common@example.com
|
||||||
|
137 | | FirstName.LastName@EasierReading.org
|
||||||
|
138 | | x@example.com
|
||||||
|
139 | | long.email-address-with-hyphens@and.subdomains.example.com
|
||||||
|
140 | | user.name+tag+sorting@example.com
|
||||||
|
141 | | name/surname@example.com
|
||||||
|
142 | | xample@s.example
|
||||||
|
143 | | " "@example.org
|
||||||
|
144 | | "john..doe"@example.org
|
||||||
|
145 | | mailhost!username@example.org
|
||||||
|
146 | | "very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com
|
||||||
|
147 | | user%example.com@example.org
|
||||||
|
148 | | user-@example.org
|
||||||
|
149 | | I❤️CHOCOLATE@example.com
|
||||||
|
150 | | this\ still\"not\\allowed@example.com
|
||||||
|
151 | | stellyamburrr985@example.com
|
||||||
|
152 | | Abc.123@example.com
|
||||||
|
153 | | user+mailbox/department=shipping@example.com
|
||||||
|
154 | | !#$%&'*+-/=?^_`.{|}~@example.com
|
||||||
|
155 | | "Abc@def"@example.com
|
||||||
|
156 | | "Fred\ Bloggs"@example.com
|
||||||
|
157 | | "Joe.\\Blow"@example.com""".split("\n")
|
||||||
|
| |_______________________________________^ SIM905
|
||||||
|
|
|
||||||
|
= help: Replace with list literal
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
132 132 | print(" x ".rsplit(sep=None, maxsplit=0))
|
||||||
|
133 133 |
|
||||||
|
134 134 | # https://github.com/astral-sh/ruff/issues/19581 - embedded quotes in raw strings
|
||||||
|
135 |-r"""simple@example.com
|
||||||
|
136 |-very.common@example.com
|
||||||
|
137 |-FirstName.LastName@EasierReading.org
|
||||||
|
138 |-x@example.com
|
||||||
|
139 |-long.email-address-with-hyphens@and.subdomains.example.com
|
||||||
|
140 |-user.name+tag+sorting@example.com
|
||||||
|
141 |-name/surname@example.com
|
||||||
|
142 |-xample@s.example
|
||||||
|
143 |-" "@example.org
|
||||||
|
144 |-"john..doe"@example.org
|
||||||
|
145 |-mailhost!username@example.org
|
||||||
|
146 |-"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com
|
||||||
|
147 |-user%example.com@example.org
|
||||||
|
148 |-user-@example.org
|
||||||
|
149 |-I❤️CHOCOLATE@example.com
|
||||||
|
150 |-this\ still\"not\\allowed@example.com
|
||||||
|
151 |-stellyamburrr985@example.com
|
||||||
|
152 |-Abc.123@example.com
|
||||||
|
153 |-user+mailbox/department=shipping@example.com
|
||||||
|
154 |-!#$%&'*+-/=?^_`.{|}~@example.com
|
||||||
|
155 |-"Abc@def"@example.com
|
||||||
|
156 |-"Fred\ Bloggs"@example.com
|
||||||
|
157 |-"Joe.\\Blow"@example.com""".split("\n")
|
||||||
|
135 |+[r"simple@example.com", r"very.common@example.com", r"FirstName.LastName@EasierReading.org", r"x@example.com", r"long.email-address-with-hyphens@and.subdomains.example.com", r"user.name+tag+sorting@example.com", r"name/surname@example.com", r"xample@s.example", r'" "@example.org', r'"john..doe"@example.org', r"mailhost!username@example.org", r'"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com', r"user%example.com@example.org", r"user-@example.org", r"I❤️CHOCOLATE@example.com", r'this\ still\"not\\allowed@example.com', r"stellyamburrr985@example.com", r"Abc.123@example.com", r"user+mailbox/department=shipping@example.com", r"!#$%&'*+-/=?^_`.{|}~@example.com", r'"Abc@def"@example.com', r'"Fred\ Bloggs"@example.com', r'"Joe.\\Blow"@example.com']
|
||||||
|
158 136 |
|
||||||
|
159 137 |
|
||||||
|
160 138 | r"""first
|
||||||
|
|
||||||
|
SIM905.py:160:1: SIM905 [*] Consider using a list literal instead of `str.split`
|
||||||
|
|
|
||||||
|
160 | / r"""first
|
||||||
|
161 | | 'no need' to escape
|
||||||
|
162 | | "swap" quote style
|
||||||
|
163 | | "use' ugly triple quotes""".split("\n")
|
||||||
|
| |_______________________________________^ SIM905
|
||||||
|
|
|
||||||
|
= help: Replace with list literal
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
157 157 | "Joe.\\Blow"@example.com""".split("\n")
|
||||||
|
158 158 |
|
||||||
|
159 159 |
|
||||||
|
160 |-r"""first
|
||||||
|
161 |-'no need' to escape
|
||||||
|
162 |-"swap" quote style
|
||||||
|
163 |-"use' ugly triple quotes""".split("\n")
|
||||||
|
160 |+[r"first", r"'no need' to escape", r'"swap" quote style', r""""use' ugly triple quotes"""]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue