mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
[refurb
] implement hardcoded-string-charset
(FURB156) (#13530)
Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
38d872ea4c
commit
73aa6ea417
8 changed files with 722 additions and 1 deletions
53
crates/ruff_linter/resources/test/fixtures/refurb/FURB156.py
vendored
Normal file
53
crates/ruff_linter/resources/test/fixtures/refurb/FURB156.py
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Errors
|
||||||
|
|
||||||
|
_ = "0123456789"
|
||||||
|
_ = "01234567"
|
||||||
|
_ = "0123456789abcdefABCDEF"
|
||||||
|
_ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
_ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
_ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
_ = " \t\n\r\v\f"
|
||||||
|
|
||||||
|
_ = "" in "1234567890"
|
||||||
|
_ = "" in "12345670"
|
||||||
|
_ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
_ = (
|
||||||
|
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'
|
||||||
|
"'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c"
|
||||||
|
)
|
||||||
|
_ = id("0123"
|
||||||
|
"4567"
|
||||||
|
"89")
|
||||||
|
_ = "" in ("123"
|
||||||
|
"456"
|
||||||
|
"789"
|
||||||
|
"0")
|
||||||
|
|
||||||
|
_ = "" in ( # comment
|
||||||
|
"123"
|
||||||
|
"456"
|
||||||
|
"789"
|
||||||
|
"0")
|
||||||
|
|
||||||
|
|
||||||
|
_ = "" in (
|
||||||
|
"123"
|
||||||
|
"456" # inline comment
|
||||||
|
"789"
|
||||||
|
"0")
|
||||||
|
|
||||||
|
_ = (
|
||||||
|
"0123456789"
|
||||||
|
).capitalize()
|
||||||
|
|
||||||
|
_ = (
|
||||||
|
"0123456789"
|
||||||
|
# with comment
|
||||||
|
).capitalize()
|
||||||
|
|
||||||
|
# Ok
|
||||||
|
|
||||||
|
_ = "1234567890"
|
||||||
|
_ = "1234"
|
||||||
|
_ = "" in "1234"
|
|
@ -1355,6 +1355,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||||
if checker.enabled(Rule::SingleItemMembershipTest) {
|
if checker.enabled(Rule::SingleItemMembershipTest) {
|
||||||
refurb::rules::single_item_membership_test(checker, expr, left, ops, comparators);
|
refurb::rules::single_item_membership_test(checker, expr, left, ops, comparators);
|
||||||
}
|
}
|
||||||
|
if checker.enabled(Rule::HardcodedStringCharset) {
|
||||||
|
refurb::rules::hardcoded_string_charset_comparison(checker, compare);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::NumberLiteral(number_literal @ ast::ExprNumberLiteral { .. }) => {
|
Expr::NumberLiteral(number_literal @ ast::ExprNumberLiteral { .. }) => {
|
||||||
if checker.source_type.is_stub() && checker.enabled(Rule::NumericLiteralTooLong) {
|
if checker.source_type.is_stub() && checker.enabled(Rule::NumericLiteralTooLong) {
|
||||||
|
@ -1364,7 +1367,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||||
refurb::rules::math_constant(checker, number_literal);
|
refurb::rules::math_constant(checker, number_literal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::StringLiteral(ast::ExprStringLiteral { value, range: _ }) => {
|
Expr::StringLiteral(string_like @ ast::ExprStringLiteral { value, range: _ }) => {
|
||||||
if checker.enabled(Rule::UnicodeKindPrefix) {
|
if checker.enabled(Rule::UnicodeKindPrefix) {
|
||||||
for string_part in value {
|
for string_part in value {
|
||||||
pyupgrade::rules::unicode_kind_prefix(checker, string_part);
|
pyupgrade::rules::unicode_kind_prefix(checker, string_part);
|
||||||
|
@ -1375,6 +1378,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||||
ruff::rules::missing_fstring_syntax(checker, string_literal);
|
ruff::rules::missing_fstring_syntax(checker, string_literal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if checker.enabled(Rule::HardcodedStringCharset) {
|
||||||
|
refurb::rules::hardcoded_string_charset_literal(checker, string_like);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::If(
|
Expr::If(
|
||||||
if_exp @ ast::ExprIf {
|
if_exp @ ast::ExprIf {
|
||||||
|
|
|
@ -1055,6 +1055,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||||
(Refurb, "148") => (RuleGroup::Preview, rules::refurb::rules::UnnecessaryEnumerate),
|
(Refurb, "148") => (RuleGroup::Preview, rules::refurb::rules::UnnecessaryEnumerate),
|
||||||
(Refurb, "152") => (RuleGroup::Preview, rules::refurb::rules::MathConstant),
|
(Refurb, "152") => (RuleGroup::Preview, rules::refurb::rules::MathConstant),
|
||||||
(Refurb, "154") => (RuleGroup::Preview, rules::refurb::rules::RepeatedGlobal),
|
(Refurb, "154") => (RuleGroup::Preview, rules::refurb::rules::RepeatedGlobal),
|
||||||
|
(Refurb, "156") => (RuleGroup::Preview, rules::refurb::rules::HardcodedStringCharset),
|
||||||
(Refurb, "157") => (RuleGroup::Preview, rules::refurb::rules::VerboseDecimalConstructor),
|
(Refurb, "157") => (RuleGroup::Preview, rules::refurb::rules::VerboseDecimalConstructor),
|
||||||
(Refurb, "161") => (RuleGroup::Stable, rules::refurb::rules::BitCount),
|
(Refurb, "161") => (RuleGroup::Stable, rules::refurb::rules::BitCount),
|
||||||
(Refurb, "163") => (RuleGroup::Stable, rules::refurb::rules::RedundantLogBase),
|
(Refurb, "163") => (RuleGroup::Stable, rules::refurb::rules::RedundantLogBase),
|
||||||
|
|
|
@ -29,6 +29,7 @@ mod tests {
|
||||||
#[test_case(Rule::UnnecessaryEnumerate, Path::new("FURB148.py"))]
|
#[test_case(Rule::UnnecessaryEnumerate, Path::new("FURB148.py"))]
|
||||||
#[test_case(Rule::MathConstant, Path::new("FURB152.py"))]
|
#[test_case(Rule::MathConstant, Path::new("FURB152.py"))]
|
||||||
#[test_case(Rule::RepeatedGlobal, Path::new("FURB154.py"))]
|
#[test_case(Rule::RepeatedGlobal, Path::new("FURB154.py"))]
|
||||||
|
#[test_case(Rule::HardcodedStringCharset, Path::new("FURB156.py"))]
|
||||||
#[test_case(Rule::VerboseDecimalConstructor, Path::new("FURB157.py"))]
|
#[test_case(Rule::VerboseDecimalConstructor, Path::new("FURB157.py"))]
|
||||||
#[test_case(Rule::UnnecessaryFromFloat, Path::new("FURB164.py"))]
|
#[test_case(Rule::UnnecessaryFromFloat, Path::new("FURB164.py"))]
|
||||||
#[test_case(Rule::PrintEmptyString, Path::new("FURB105.py"))]
|
#[test_case(Rule::PrintEmptyString, Path::new("FURB105.py"))]
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::importer::ImportRequest;
|
||||||
|
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||||
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
use ruff_python_ast::{CmpOp, Expr, ExprCompare, ExprStringLiteral};
|
||||||
|
use ruff_text_size::TextRange;
|
||||||
|
|
||||||
|
/// ## What it does
|
||||||
|
/// Checks for uses of hardcoded charsets, which are defined in Python string module.
|
||||||
|
///
|
||||||
|
/// ## Why is this bad?
|
||||||
|
/// Usage of named charsets from the standard library is more readable and less error-prone.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```python
|
||||||
|
/// x = "0123456789"
|
||||||
|
/// y in "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead
|
||||||
|
/// ```python
|
||||||
|
/// import string
|
||||||
|
///
|
||||||
|
/// x = string.digits
|
||||||
|
/// y in string.ascii_lowercase
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## References
|
||||||
|
/// - [Python documentation: String constants](https://docs.python.org/3/library/string.html#string-constants)
|
||||||
|
#[violation]
|
||||||
|
pub struct HardcodedStringCharset {
|
||||||
|
name: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AlwaysFixableViolation for HardcodedStringCharset {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Use of hardcoded string charset")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fix_title(&self) -> String {
|
||||||
|
let HardcodedStringCharset { name } = self;
|
||||||
|
format!("Replace hardcoded charset with `string.{name}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NamedCharset {
|
||||||
|
name: &'static str,
|
||||||
|
bytes: &'static [u8],
|
||||||
|
ascii_char_set: AsciiCharSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents the set of ascii characters in form of a bitset.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
|
struct AsciiCharSet(u128);
|
||||||
|
|
||||||
|
impl AsciiCharSet {
|
||||||
|
/// Creates the set of ascii characters from `bytes`.
|
||||||
|
/// Returns None if there is non-ascii byte.
|
||||||
|
const fn from_bytes(bytes: &[u8]) -> Option<Self> {
|
||||||
|
// TODO: simplify implementation, when const-traits are supported
|
||||||
|
// https://github.com/rust-lang/rust-project-goals/issues/106
|
||||||
|
let mut bitset = 0;
|
||||||
|
let mut i = 0;
|
||||||
|
while i < bytes.len() {
|
||||||
|
if !bytes[i].is_ascii() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
bitset |= 1 << bytes[i];
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
Some(Self(bitset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NamedCharset {
|
||||||
|
const fn new(name: &'static str, bytes: &'static [u8]) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
bytes,
|
||||||
|
// SAFETY: The named charset is guaranteed to have only ascii bytes.
|
||||||
|
// TODO: replace with `.unwrap()`, when `Option::unwrap` will be stable in `const fn`
|
||||||
|
// https://github.com/rust-lang/rust/issues/67441
|
||||||
|
ascii_char_set: match AsciiCharSet::from_bytes(bytes) {
|
||||||
|
Some(ascii_char_set) => ascii_char_set,
|
||||||
|
None => unreachable!(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const KNOWN_NAMED_CHARSETS: [NamedCharset; 9] = [
|
||||||
|
NamedCharset::new(
|
||||||
|
"ascii_letters",
|
||||||
|
b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||||
|
),
|
||||||
|
NamedCharset::new("ascii_lowercase", b"abcdefghijklmnopqrstuvwxyz"),
|
||||||
|
NamedCharset::new("ascii_uppercase", b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
|
||||||
|
NamedCharset::new("digits", b"0123456789"),
|
||||||
|
NamedCharset::new("hexdigits", b"0123456789abcdefABCDEF"),
|
||||||
|
NamedCharset::new("octdigits", b"01234567"),
|
||||||
|
NamedCharset::new("punctuation", b"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"),
|
||||||
|
NamedCharset::new(
|
||||||
|
"printable",
|
||||||
|
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"\
|
||||||
|
#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c",
|
||||||
|
),
|
||||||
|
NamedCharset::new("whitespace", b" \t\n\r\x0b\x0c"),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn check_charset_as_set(bytes: &[u8]) -> Option<&NamedCharset> {
|
||||||
|
let ascii_char_set = AsciiCharSet::from_bytes(bytes)?;
|
||||||
|
|
||||||
|
KNOWN_NAMED_CHARSETS
|
||||||
|
.iter()
|
||||||
|
.find(|&charset| charset.ascii_char_set == ascii_char_set)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_charset_exact(bytes: &[u8]) -> Option<&NamedCharset> {
|
||||||
|
KNOWN_NAMED_CHARSETS
|
||||||
|
.iter()
|
||||||
|
.find(|&charset| charset.bytes == bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_diagnostic(checker: &mut Checker, range: TextRange, charset: &NamedCharset) {
|
||||||
|
let name = charset.name;
|
||||||
|
let mut diagnostic = Diagnostic::new(HardcodedStringCharset { name }, range);
|
||||||
|
diagnostic.try_set_fix(|| {
|
||||||
|
let (edit, binding) = checker.importer().get_or_import_symbol(
|
||||||
|
&ImportRequest::import("string", name),
|
||||||
|
range.start(),
|
||||||
|
checker.semantic(),
|
||||||
|
)?;
|
||||||
|
Ok(Fix::safe_edits(
|
||||||
|
Edit::range_replacement(binding, range),
|
||||||
|
[edit],
|
||||||
|
))
|
||||||
|
});
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FURB156
|
||||||
|
pub(crate) fn hardcoded_string_charset_comparison(checker: &mut Checker, compare: &ExprCompare) {
|
||||||
|
let (
|
||||||
|
[CmpOp::In | CmpOp::NotIn],
|
||||||
|
[Expr::StringLiteral(string_literal @ ExprStringLiteral { value, .. })],
|
||||||
|
) = (compare.ops.as_ref(), compare.comparators.as_ref())
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes = value.to_str().as_bytes();
|
||||||
|
|
||||||
|
let Some(charset) = check_charset_as_set(bytes) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// In this case the diagnostic will be emitted via string_literal check.
|
||||||
|
if charset.bytes == bytes {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
push_diagnostic(checker, string_literal.range, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FURB156
|
||||||
|
pub(crate) fn hardcoded_string_charset_literal(checker: &mut Checker, expr: &ExprStringLiteral) {
|
||||||
|
if let Some(charset) = check_charset_exact(expr.value.to_str().as_bytes()) {
|
||||||
|
push_diagnostic(checker, expr.range, charset);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ pub(crate) use check_and_remove_from_set::*;
|
||||||
pub(crate) use delete_full_slice::*;
|
pub(crate) use delete_full_slice::*;
|
||||||
pub(crate) use for_loop_set_mutations::*;
|
pub(crate) use for_loop_set_mutations::*;
|
||||||
pub(crate) use fstring_number_format::*;
|
pub(crate) use fstring_number_format::*;
|
||||||
|
pub(crate) use hardcoded_string_charset::*;
|
||||||
pub(crate) use hashlib_digest_hex::*;
|
pub(crate) use hashlib_digest_hex::*;
|
||||||
pub(crate) use if_exp_instead_of_or_operator::*;
|
pub(crate) use if_exp_instead_of_or_operator::*;
|
||||||
pub(crate) use if_expr_min_max::*;
|
pub(crate) use if_expr_min_max::*;
|
||||||
|
@ -36,6 +37,7 @@ mod check_and_remove_from_set;
|
||||||
mod delete_full_slice;
|
mod delete_full_slice;
|
||||||
mod for_loop_set_mutations;
|
mod for_loop_set_mutations;
|
||||||
mod fstring_number_format;
|
mod fstring_number_format;
|
||||||
|
mod hardcoded_string_charset;
|
||||||
mod hashlib_digest_hex;
|
mod hashlib_digest_hex;
|
||||||
mod if_exp_instead_of_or_operator;
|
mod if_exp_instead_of_or_operator;
|
||||||
mod if_expr_min_max;
|
mod if_expr_min_max;
|
||||||
|
|
|
@ -0,0 +1,486 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/refurb/mod.rs
|
||||||
|
---
|
||||||
|
FURB156.py:3:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
1 | # Errors
|
||||||
|
2 |
|
||||||
|
3 | _ = "0123456789"
|
||||||
|
| ^^^^^^^^^^^^ FURB156
|
||||||
|
4 | _ = "01234567"
|
||||||
|
5 | _ = "0123456789abcdefABCDEF"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 |-_ = "0123456789"
|
||||||
|
4 |+_ = string.digits
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
5 6 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 7 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
FURB156.py:4:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
3 | _ = "0123456789"
|
||||||
|
4 | _ = "01234567"
|
||||||
|
| ^^^^^^^^^^ FURB156
|
||||||
|
5 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.octdigits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 |-_ = "01234567"
|
||||||
|
5 |+_ = string.octdigits
|
||||||
|
5 6 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 7 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 8 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
FURB156.py:5:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
3 | _ = "0123456789"
|
||||||
|
4 | _ = "01234567"
|
||||||
|
5 | _ = "0123456789abcdefABCDEF"
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ FURB156
|
||||||
|
6 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.hexdigits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
5 |-_ = "0123456789abcdefABCDEF"
|
||||||
|
6 |+_ = string.hexdigits
|
||||||
|
6 7 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 8 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 9 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
|
FURB156.py:6:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
4 | _ = "01234567"
|
||||||
|
5 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB156
|
||||||
|
7 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.ascii_lowercase`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
5 6 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 |-_ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 |+_ = string.ascii_lowercase
|
||||||
|
7 8 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 9 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 10 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
|
||||||
|
FURB156.py:7:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
5 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB156
|
||||||
|
8 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.ascii_uppercase`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
5 6 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 7 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 |-_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 |+_ = string.ascii_uppercase
|
||||||
|
8 9 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 10 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
10 11 | _ = " \t\n\r\v\f"
|
||||||
|
|
||||||
|
FURB156.py:8:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
6 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB156
|
||||||
|
9 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
10 | _ = " \t\n\r\v\f"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.ascii_letters`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
5 6 | _ = "0123456789abcdefABCDEF"
|
||||||
|
6 7 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 8 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 |-_ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 |+_ = string.ascii_letters
|
||||||
|
9 10 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
10 11 | _ = " \t\n\r\v\f"
|
||||||
|
11 12 |
|
||||||
|
|
||||||
|
FURB156.py:9:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
7 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB156
|
||||||
|
10 | _ = " \t\n\r\v\f"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.punctuation`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
6 7 | _ = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
7 8 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 9 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 |-_ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
10 |+_ = string.punctuation
|
||||||
|
10 11 | _ = " \t\n\r\v\f"
|
||||||
|
11 12 |
|
||||||
|
12 13 | _ = "" in "1234567890"
|
||||||
|
|
||||||
|
FURB156.py:10:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
8 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
10 | _ = " \t\n\r\v\f"
|
||||||
|
| ^^^^^^^^^^^^^ FURB156
|
||||||
|
11 |
|
||||||
|
12 | _ = "" in "1234567890"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.whitespace`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
7 8 | _ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
8 9 | _ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
9 10 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
10 |-_ = " \t\n\r\v\f"
|
||||||
|
11 |+_ = string.whitespace
|
||||||
|
11 12 |
|
||||||
|
12 13 | _ = "" in "1234567890"
|
||||||
|
13 14 | _ = "" in "12345670"
|
||||||
|
|
||||||
|
FURB156.py:12:11: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
10 | _ = " \t\n\r\v\f"
|
||||||
|
11 |
|
||||||
|
12 | _ = "" in "1234567890"
|
||||||
|
| ^^^^^^^^^^^^ FURB156
|
||||||
|
13 | _ = "" in "12345670"
|
||||||
|
14 | _ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
9 10 | _ = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
|
||||||
|
10 11 | _ = " \t\n\r\v\f"
|
||||||
|
11 12 |
|
||||||
|
12 |-_ = "" in "1234567890"
|
||||||
|
13 |+_ = "" in string.digits
|
||||||
|
13 14 | _ = "" in "12345670"
|
||||||
|
14 15 | _ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
15 16 | _ = (
|
||||||
|
|
||||||
|
FURB156.py:13:11: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
12 | _ = "" in "1234567890"
|
||||||
|
13 | _ = "" in "12345670"
|
||||||
|
| ^^^^^^^^^^ FURB156
|
||||||
|
14 | _ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
15 | _ = (
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.octdigits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
10 11 | _ = " \t\n\r\v\f"
|
||||||
|
11 12 |
|
||||||
|
12 13 | _ = "" in "1234567890"
|
||||||
|
13 |-_ = "" in "12345670"
|
||||||
|
14 |+_ = "" in string.octdigits
|
||||||
|
14 15 | _ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
15 16 | _ = (
|
||||||
|
16 17 | '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'
|
||||||
|
|
||||||
|
FURB156.py:14:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
12 | _ = "" in "1234567890"
|
||||||
|
13 | _ = "" in "12345670"
|
||||||
|
14 | _ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB156
|
||||||
|
15 | _ = (
|
||||||
|
16 | '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.printable`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
11 12 |
|
||||||
|
12 13 | _ = "" in "1234567890"
|
||||||
|
13 14 | _ = "" in "12345670"
|
||||||
|
14 |-_ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
15 |+_ = string.printable
|
||||||
|
15 16 | _ = (
|
||||||
|
16 17 | '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'
|
||||||
|
17 18 | "'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c"
|
||||||
|
|
||||||
|
FURB156.py:16:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
14 | _ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
15 | _ = (
|
||||||
|
16 | '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'
|
||||||
|
| _____^
|
||||||
|
17 | | "'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c"
|
||||||
|
| |________________________________________________^ FURB156
|
||||||
|
18 | )
|
||||||
|
19 | _ = id("0123"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.printable`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
13 14 | _ = "" in "12345670"
|
||||||
|
14 15 | _ = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
|
||||||
|
15 16 | _ = (
|
||||||
|
16 |- '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'
|
||||||
|
17 |- "'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c"
|
||||||
|
17 |+ string.printable
|
||||||
|
18 18 | )
|
||||||
|
19 19 | _ = id("0123"
|
||||||
|
20 20 | "4567"
|
||||||
|
|
||||||
|
FURB156.py:19:8: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
17 | "'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c"
|
||||||
|
18 | )
|
||||||
|
19 | _ = id("0123"
|
||||||
|
| ________^
|
||||||
|
20 | | "4567"
|
||||||
|
21 | | "89")
|
||||||
|
| |___________^ FURB156
|
||||||
|
22 | _ = "" in ("123"
|
||||||
|
23 | "456"
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
16 17 | '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'
|
||||||
|
17 18 | "'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c"
|
||||||
|
18 19 | )
|
||||||
|
19 |-_ = id("0123"
|
||||||
|
20 |- "4567"
|
||||||
|
21 |- "89")
|
||||||
|
20 |+_ = id(string.digits)
|
||||||
|
22 21 | _ = "" in ("123"
|
||||||
|
23 22 | "456"
|
||||||
|
24 23 | "789"
|
||||||
|
|
||||||
|
FURB156.py:22:12: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
20 | "4567"
|
||||||
|
21 | "89")
|
||||||
|
22 | _ = "" in ("123"
|
||||||
|
| ____________^
|
||||||
|
23 | | "456"
|
||||||
|
24 | | "789"
|
||||||
|
25 | | "0")
|
||||||
|
| |______________^ FURB156
|
||||||
|
26 |
|
||||||
|
27 | _ = "" in ( # comment
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
19 20 | _ = id("0123"
|
||||||
|
20 21 | "4567"
|
||||||
|
21 22 | "89")
|
||||||
|
22 |-_ = "" in ("123"
|
||||||
|
23 |- "456"
|
||||||
|
24 |- "789"
|
||||||
|
25 |- "0")
|
||||||
|
23 |+_ = "" in (string.digits)
|
||||||
|
26 24 |
|
||||||
|
27 25 | _ = "" in ( # comment
|
||||||
|
28 26 | "123"
|
||||||
|
|
||||||
|
FURB156.py:28:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
27 | _ = "" in ( # comment
|
||||||
|
28 | "123"
|
||||||
|
| _____^
|
||||||
|
29 | | "456"
|
||||||
|
30 | | "789"
|
||||||
|
31 | | "0")
|
||||||
|
| |_______^ FURB156
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
25 26 | "0")
|
||||||
|
26 27 |
|
||||||
|
27 28 | _ = "" in ( # comment
|
||||||
|
28 |- "123"
|
||||||
|
29 |- "456"
|
||||||
|
30 |- "789"
|
||||||
|
31 |- "0")
|
||||||
|
29 |+ string.digits)
|
||||||
|
32 30 |
|
||||||
|
33 31 |
|
||||||
|
34 32 | _ = "" in (
|
||||||
|
|
||||||
|
FURB156.py:35:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
34 | _ = "" in (
|
||||||
|
35 | "123"
|
||||||
|
| _____^
|
||||||
|
36 | | "456" # inline comment
|
||||||
|
37 | | "789"
|
||||||
|
38 | | "0")
|
||||||
|
| |_______^ FURB156
|
||||||
|
39 |
|
||||||
|
40 | _ = (
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
32 33 |
|
||||||
|
33 34 |
|
||||||
|
34 35 | _ = "" in (
|
||||||
|
35 |- "123"
|
||||||
|
36 |- "456" # inline comment
|
||||||
|
37 |- "789"
|
||||||
|
38 |- "0")
|
||||||
|
36 |+ string.digits)
|
||||||
|
39 37 |
|
||||||
|
40 38 | _ = (
|
||||||
|
41 39 | "0123456789"
|
||||||
|
|
||||||
|
FURB156.py:41:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
40 | _ = (
|
||||||
|
41 | "0123456789"
|
||||||
|
| ^^^^^^^^^^^^ FURB156
|
||||||
|
42 | ).capitalize()
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
38 39 | "0")
|
||||||
|
39 40 |
|
||||||
|
40 41 | _ = (
|
||||||
|
41 |- "0123456789"
|
||||||
|
42 |+ string.digits
|
||||||
|
42 43 | ).capitalize()
|
||||||
|
43 44 |
|
||||||
|
44 45 | _ = (
|
||||||
|
|
||||||
|
FURB156.py:45:5: FURB156 [*] Use of hardcoded string charset
|
||||||
|
|
|
||||||
|
44 | _ = (
|
||||||
|
45 | "0123456789"
|
||||||
|
| ^^^^^^^^^^^^ FURB156
|
||||||
|
46 | # with comment
|
||||||
|
47 | ).capitalize()
|
||||||
|
|
|
||||||
|
= help: Replace hardcoded charset with `string.digits`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
1 1 | # Errors
|
||||||
|
2 |+import string
|
||||||
|
2 3 |
|
||||||
|
3 4 | _ = "0123456789"
|
||||||
|
4 5 | _ = "01234567"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
42 43 | ).capitalize()
|
||||||
|
43 44 |
|
||||||
|
44 45 | _ = (
|
||||||
|
45 |- "0123456789"
|
||||||
|
46 |+ string.digits
|
||||||
|
46 47 | # with comment
|
||||||
|
47 48 | ).capitalize()
|
||||||
|
48 49 |
|
1
ruff.schema.json
generated
1
ruff.schema.json
generated
|
@ -3279,6 +3279,7 @@
|
||||||
"FURB15",
|
"FURB15",
|
||||||
"FURB152",
|
"FURB152",
|
||||||
"FURB154",
|
"FURB154",
|
||||||
|
"FURB156",
|
||||||
"FURB157",
|
"FURB157",
|
||||||
"FURB16",
|
"FURB16",
|
||||||
"FURB161",
|
"FURB161",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue