diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI054.py b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI054.py new file mode 100644 index 0000000000000..9ea9eec654165 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI054.py @@ -0,0 +1,20 @@ +field01: int = 0xFFFFFFFF +field02: int = 0xFFFFFFFFF +field03: int = -0xFFFFFFFF +field04: int = -0xFFFFFFFFF + +field05: int = 1234567890 +field06: int = 12_456_890 +field07: int = 12345678901 +field08: int = -1234567801 +field09: int = -234_567_890 + +field10: float = 123.456789 +field11: float = 123.4567890 +field12: float = -123.456789 +field13: float = -123.567_890 + +field14: complex = 1e1234567j +field15: complex = 1e12345678j +field16: complex = -1e1234567j +field17: complex = 1e123456789j diff --git a/crates/ruff/resources/test/fixtures/flake8_pyi/PYI054.pyi b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI054.pyi new file mode 100644 index 0000000000000..73c9a37347761 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/flake8_pyi/PYI054.pyi @@ -0,0 +1,20 @@ +field01: int = 0xFFFFFFFF +field02: int = 0xFFFFFFFFF # Error: PYI054 +field03: int = -0xFFFFFFFF +field04: int = -0xFFFFFFFFF # Error: PYI054 + +field05: int = 1234567890 +field06: int = 12_456_890 +field07: int = 12345678901 # Error: PYI054 +field08: int = -1234567801 +field09: int = -234_567_890 # Error: PYI054 + +field10: float = 123.456789 +field11: float = 123.4567890 # Error: PYI054 +field12: float = -123.456789 +field13: float = -123.567_890 # Error: PYI054 + +field14: complex = 1e1234567j +field15: complex = 1e12345678j # Error: PYI054 +field16: complex = -1e1234567j +field17: complex = 1e123456789j # Error: PYI054 diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 514844ee48f9a..a28bccfa122c8 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -3410,9 +3410,19 @@ where } } } + Expr::Constant(ast::ExprConstant { + value: Constant::Int(_) | Constant::Float(_) | Constant::Complex { .. }, + kind: _, + range: _, + }) => { + if self.is_stub && self.enabled(Rule::NumericLiteralTooLong) { + flake8_pyi::rules::numeric_literal_too_long(self, expr); + } + } Expr::Constant(ast::ExprConstant { value: Constant::Bytes(_), - .. + kind: _, + range: _, }) => { if self.is_stub && self.enabled(Rule::StringOrBytesTooLong) { flake8_pyi::rules::string_or_bytes_too_long(self, expr); diff --git a/crates/ruff/src/codes.rs b/crates/ruff/src/codes.rs index e7d12a17ae0f1..b2585fa84a5d4 100644 --- a/crates/ruff/src/codes.rs +++ b/crates/ruff/src/codes.rs @@ -601,6 +601,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8Pyi, "045") => (RuleGroup::Unspecified, Rule::IterMethodReturnIterable), (Flake8Pyi, "048") => (RuleGroup::Unspecified, Rule::StubBodyMultipleStatements), (Flake8Pyi, "052") => (RuleGroup::Unspecified, Rule::UnannotatedAssignmentInStub), + (Flake8Pyi, "054") => (RuleGroup::Unspecified, Rule::NumericLiteralTooLong), (Flake8Pyi, "053") => (RuleGroup::Unspecified, Rule::StringOrBytesTooLong), // flake8-pytest-style diff --git a/crates/ruff/src/registry.rs b/crates/ruff/src/registry.rs index 67af1e4572ae6..2b948c5b665e8 100644 --- a/crates/ruff/src/registry.rs +++ b/crates/ruff/src/registry.rs @@ -524,6 +524,7 @@ ruff_macros::register_rules!( rules::flake8_pyi::rules::NonEmptyStubBody, rules::flake8_pyi::rules::PassInClassBody, rules::flake8_pyi::rules::PassStatementStubBody, + rules::flake8_pyi::rules::NumericLiteralTooLong, rules::flake8_pyi::rules::QuotedAnnotationInStub, rules::flake8_pyi::rules::SnakeCaseTypeAlias, rules::flake8_pyi::rules::StubBodyMultipleStatements, diff --git a/crates/ruff/src/rules/flake8_pyi/mod.rs b/crates/ruff/src/rules/flake8_pyi/mod.rs index 9a2d112be7955..b2745a523e81b 100644 --- a/crates/ruff/src/rules/flake8_pyi/mod.rs +++ b/crates/ruff/src/rules/flake8_pyi/mod.rs @@ -30,6 +30,8 @@ mod tests { #[test_case(Rule::CollectionsNamedTuple, Path::new("PYI024.pyi"))] #[test_case(Rule::IterMethodReturnIterable, Path::new("PYI045.py"))] #[test_case(Rule::IterMethodReturnIterable, Path::new("PYI045.pyi"))] + #[test_case(Rule::NumericLiteralTooLong, Path::new("PYI054.py"))] + #[test_case(Rule::NumericLiteralTooLong, Path::new("PYI054.pyi"))] #[test_case(Rule::NonEmptyStubBody, Path::new("PYI010.py"))] #[test_case(Rule::NonEmptyStubBody, Path::new("PYI010.pyi"))] #[test_case(Rule::PassInClassBody, Path::new("PYI012.py"))] diff --git a/crates/ruff/src/rules/flake8_pyi/rules/mod.rs b/crates/ruff/src/rules/flake8_pyi/rules/mod.rs index 0be2c5c3bfd67..662ade7444465 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/mod.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/mod.rs @@ -12,6 +12,7 @@ pub(crate) use iter_method_return_iterable::{ iter_method_return_iterable, IterMethodReturnIterable, }; pub(crate) use non_empty_stub_body::{non_empty_stub_body, NonEmptyStubBody}; +pub(crate) use numeric_literal_too_long::{numeric_literal_too_long, NumericLiteralTooLong}; pub(crate) use pass_in_class_body::{pass_in_class_body, PassInClassBody}; pub(crate) use pass_statement_stub_body::{pass_statement_stub_body, PassStatementStubBody}; pub(crate) use prefix_type_params::{prefix_type_params, UnprefixedTypeParam}; @@ -44,6 +45,7 @@ mod duplicate_union_member; mod ellipsis_in_non_empty_class_body; mod iter_method_return_iterable; mod non_empty_stub_body; +mod numeric_literal_too_long; mod pass_in_class_body; mod pass_statement_stub_body; mod prefix_type_params; diff --git a/crates/ruff/src/rules/flake8_pyi/rules/numeric_literal_too_long.rs b/crates/ruff/src/rules/flake8_pyi/rules/numeric_literal_too_long.rs new file mode 100644 index 0000000000000..28a49c0547fbc --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/rules/numeric_literal_too_long.rs @@ -0,0 +1,58 @@ +use ruff_text_size::TextSize; +use rustpython_parser::ast::{Expr, Ranged}; + +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; +use ruff_macros::{derive_message_formats, violation}; + +use crate::checkers::ast::Checker; +use crate::registry::AsRule; + +#[violation] +pub struct NumericLiteralTooLong; + +/// ## What it does +/// Checks for numeric literals with a string representation longer than ten +/// characters. +/// +/// ## Why is this bad? +/// If a function has a default value where the literal representation is +/// greater than 50 characters, it is likely to be an implementation detail or +/// a constant that varies depending on the system you're running on. +/// +/// Consider replacing such constants with ellipses (`...`). +/// +/// ## Example +/// ```python +/// def foo(arg: int = 12345678901) -> None: ... +/// ``` +/// +/// Use instead: +/// ```python +/// def foo(arg: int = ...) -> None: ... +/// ``` +impl AlwaysAutofixableViolation for NumericLiteralTooLong { + #[derive_message_formats] + fn message(&self) -> String { + format!("Numeric literals with a string representation longer than ten characters are not permitted") + } + + fn autofix_title(&self) -> String { + "Replace with `...`".to_string() + } +} + +/// PYI054 +pub(crate) fn numeric_literal_too_long(checker: &mut Checker, expr: &Expr) { + if expr.range().len() <= TextSize::new(10) { + return; + } + + let mut diagnostic = Diagnostic::new(NumericLiteralTooLong, expr.range()); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.set_fix(Fix::suggested(Edit::range_replacement( + "...".to_string(), + expr.range(), + ))); + } + checker.diagnostics.push(diagnostic); +} diff --git a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs index c9224d9c5759b..933d6d377fe61 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs @@ -96,6 +96,9 @@ fn is_valid_default_value_with_annotation( model: &SemanticModel, ) -> bool { match default { + Expr::Constant(_) => { + return true; + } Expr::List(ast::ExprList { elts, .. }) | Expr::Tuple(ast::ExprTuple { elts, .. }) | Expr::Set(ast::ExprSet { elts, range: _ }) => { @@ -118,65 +121,29 @@ fn is_valid_default_value_with_annotation( }) && is_valid_default_value_with_annotation(v, false, locator, model) }); } - Expr::Constant(ast::ExprConstant { - value: Constant::Ellipsis | Constant::None, - .. - }) => { - return true; - } - Expr::Constant(ast::ExprConstant { - value: Constant::Str(..) | Constant::Bytes(..), - .. - }) => return true, - // Ex) `123`, `True`, `False`, `3.14` - Expr::Constant(ast::ExprConstant { - value: Constant::Int(..) | Constant::Bool(..) | Constant::Float(..), - .. - }) => { - return locator.slice(default.range()).len() <= 10; - } - // Ex) `2j` - Expr::Constant(ast::ExprConstant { - value: Constant::Complex { real, .. }, - .. - }) => { - if *real == 0.0 { - return locator.slice(default.range()).len() <= 10; - } - } Expr::UnaryOp(ast::ExprUnaryOp { op: Unaryop::USub, operand, range: _, }) => { - // Ex) `-1`, `-3.14` - if let Expr::Constant(ast::ExprConstant { - value: Constant::Int(..) | Constant::Float(..), - .. - }) = operand.as_ref() - { - return locator.slice(operand.range()).len() <= 10; - } - // Ex) `-2j` - if let Expr::Constant(ast::ExprConstant { - value: Constant::Complex { real, .. }, - .. - }) = operand.as_ref() - { - if *real == 0.0 { - return locator.slice(operand.range()).len() <= 10; - } - } - // Ex) `-math.inf`, `-math.pi`, etc. - if let Expr::Attribute(_) = operand.as_ref() { - if model.resolve_call_path(operand).map_or(false, |call_path| { - ALLOWED_MATH_ATTRIBUTES_IN_DEFAULTS.iter().any(|target| { - // reject `-math.nan` - call_path.as_slice() == *target && *target != ["math", "nan"] - }) - }) { - return true; + match operand.as_ref() { + // Ex) `-1`, `-3.14`, `2j` + Expr::Constant(ast::ExprConstant { + value: Constant::Int(..) | Constant::Float(..) | Constant::Complex { .. }, + .. + }) => return true, + // Ex) `-math.inf`, `-math.pi`, etc. + Expr::Attribute(_) => { + if model.resolve_call_path(operand).map_or(false, |call_path| { + ALLOWED_MATH_ATTRIBUTES_IN_DEFAULTS.iter().any(|target| { + // reject `-math.nan` + call_path.as_slice() == *target && *target != ["math", "nan"] + }) + }) { + return true; + } } + _ => {} } } Expr::BinOp(ast::ExprBinOp { diff --git a/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs b/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs index 459f17f489170..cecaed2685707 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs @@ -1,6 +1,6 @@ use rustpython_parser::ast::{self, Constant, Expr, Ranged}; -use ruff_diagnostics::{Diagnostic, Edit, Fix, Violation}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; @@ -28,11 +28,15 @@ pub struct StringOrBytesTooLong; /// ```python /// def foo(arg: str = ...) -> None: ... /// ``` -impl Violation for StringOrBytesTooLong { +impl AlwaysAutofixableViolation for StringOrBytesTooLong { #[derive_message_formats] fn message(&self) -> String { format!("String and bytes literals longer than 50 characters are not permitted") } + + fn autofix_title(&self) -> String { + "Replace with `...`".to_string() + } } /// PYI053 @@ -48,7 +52,6 @@ pub(crate) fn string_or_bytes_too_long(checker: &mut Checker, expr: &Expr) { }) => bytes.len(), _ => return, }; - if length <= 50 { return; } @@ -60,7 +63,5 @@ pub(crate) fn string_or_bytes_too_long(checker: &mut Checker, expr: &Expr) { expr.range(), ))); } - checker - .diagnostics - .push(Diagnostic::new(StringOrBytesTooLong, expr.range())); + checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI053_PYI053.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI053_PYI053.pyi.snap index 04eb3a9799ed5..8c3fa6898c535 100644 --- a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI053_PYI053.pyi.snap +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI053_PYI053.pyi.snap @@ -1,7 +1,7 @@ --- source: crates/ruff/src/rules/flake8_pyi/mod.rs --- -PYI053.pyi:3:14: PYI053 String and bytes literals longer than 50 characters are not permitted +PYI053.pyi:3:14: PYI053 [*] String and bytes literals longer than 50 characters are not permitted | 3 | def f1(x: str = "50 character stringggggggggggggggggggggggggggggggg") -> None: ... # OK 4 | def f2( @@ -10,8 +10,18 @@ PYI053.pyi:3:14: PYI053 String and bytes literals longer than 50 characters are 6 | ) -> None: ... 7 | def f3( | + = help: Replace with `...` -PYI053.pyi:9:14: PYI053 String and bytes literals longer than 50 characters are not permitted +ℹ Suggested fix +1 1 | def f1(x: str = "50 character stringggggggggggggggggggggggggggggggg") -> None: ... # OK +2 2 | def f2( +3 |- x: str = "51 character stringgggggggggggggggggggggggggggggggg", # Error: PYI053 + 3 |+ x: str = ..., # Error: PYI053 +4 4 | ) -> None: ... +5 5 | def f3( +6 6 | x: str = "50 character stringgggggggggggggggggggggggggggggg\U0001f600", # OK + +PYI053.pyi:9:14: PYI053 [*] String and bytes literals longer than 50 characters are not permitted | 9 | ) -> None: ... 10 | def f4( @@ -20,8 +30,19 @@ PYI053.pyi:9:14: PYI053 String and bytes literals longer than 50 characters are 12 | ) -> None: ... 13 | def f5( | + = help: Replace with `...` + +ℹ Suggested fix +6 6 | x: str = "50 character stringgggggggggggggggggggggggggggggg\U0001f600", # OK +7 7 | ) -> None: ... +8 8 | def f4( +9 |- x: str = "51 character stringggggggggggggggggggggggggggggggg\U0001f600", # Error: PYI053 + 9 |+ x: str = ..., # Error: PYI053 +10 10 | ) -> None: ... +11 11 | def f5( +12 12 | x: bytes = b"50 character byte stringgggggggggggggggggggggggggg", # OK -PYI053.pyi:21:16: PYI053 String and bytes literals longer than 50 characters are not permitted +PYI053.pyi:21:16: PYI053 [*] String and bytes literals longer than 50 characters are not permitted | 21 | ) -> None: ... 22 | def f8( @@ -29,8 +50,19 @@ PYI053.pyi:21:16: PYI053 String and bytes literals longer than 50 characters are | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI053 24 | ) -> None: ... | + = help: Replace with `...` + +ℹ Suggested fix +18 18 | x: bytes = b"50 character byte stringggggggggggggggggggggggggg\xff", # OK +19 19 | ) -> None: ... +20 20 | def f8( +21 |- x: bytes = b"51 character byte stringgggggggggggggggggggggggggg\xff", # Error: PYI053 + 21 |+ x: bytes = ..., # Error: PYI053 +22 22 | ) -> None: ... +23 23 | +24 24 | foo: str = "50 character stringggggggggggggggggggggggggggggggg" # OK -PYI053.pyi:26:12: PYI053 String and bytes literals longer than 50 characters are not permitted +PYI053.pyi:26:12: PYI053 [*] String and bytes literals longer than 50 characters are not permitted | 26 | foo: str = "50 character stringggggggggggggggggggggggggggggggg" # OK 27 | @@ -39,13 +71,32 @@ PYI053.pyi:26:12: PYI053 String and bytes literals longer than 50 characters are 29 | 30 | baz: bytes = b"50 character byte stringgggggggggggggggggggggggggg" # OK | + = help: Replace with `...` -PYI053.pyi:30:14: PYI053 String and bytes literals longer than 50 characters are not permitted +ℹ Suggested fix +23 23 | +24 24 | foo: str = "50 character stringggggggggggggggggggggggggggggggg" # OK +25 25 | +26 |-bar: str = "51 character stringgggggggggggggggggggggggggggggggg" # Error: PYI053 + 26 |+bar: str = ... # Error: PYI053 +27 27 | +28 28 | baz: bytes = b"50 character byte stringgggggggggggggggggggggggggg" # OK +29 29 | + +PYI053.pyi:30:14: PYI053 [*] String and bytes literals longer than 50 characters are not permitted | 30 | baz: bytes = b"50 character byte stringgggggggggggggggggggggggggg" # OK 31 | 32 | qux: bytes = b"51 character byte stringggggggggggggggggggggggggggg\xff" # Error: PYI053 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI053 | + = help: Replace with `...` + +ℹ Suggested fix +27 27 | +28 28 | baz: bytes = b"50 character byte stringgggggggggggggggggggggggggg" # OK +29 29 | +30 |-qux: bytes = b"51 character byte stringggggggggggggggggggggggggggg\xff" # Error: PYI053 + 30 |+qux: bytes = ... # Error: PYI053 diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI054_PYI054.py.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI054_PYI054.py.snap new file mode 100644 index 0000000000000..d1aa2e9116558 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI054_PYI054.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- + diff --git a/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI054_PYI054.pyi.snap b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI054_PYI054.pyi.snap new file mode 100644 index 0000000000000..b31422cdda1f8 --- /dev/null +++ b/crates/ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI054_PYI054.pyi.snap @@ -0,0 +1,161 @@ +--- +source: crates/ruff/src/rules/flake8_pyi/mod.rs +--- +PYI054.pyi:2:16: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | +2 | field01: int = 0xFFFFFFFF +3 | field02: int = 0xFFFFFFFFF # Error: PYI054 + | ^^^^^^^^^^^ PYI054 +4 | field03: int = -0xFFFFFFFF +5 | field04: int = -0xFFFFFFFFF # Error: PYI054 + | + = help: Replace with `...` + +ℹ Suggested fix +1 1 | field01: int = 0xFFFFFFFF +2 |-field02: int = 0xFFFFFFFFF # Error: PYI054 + 2 |+field02: int = ... # Error: PYI054 +3 3 | field03: int = -0xFFFFFFFF +4 4 | field04: int = -0xFFFFFFFFF # Error: PYI054 +5 5 | + +PYI054.pyi:4:17: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | +4 | field02: int = 0xFFFFFFFFF # Error: PYI054 +5 | field03: int = -0xFFFFFFFF +6 | field04: int = -0xFFFFFFFFF # Error: PYI054 + | ^^^^^^^^^^^ PYI054 +7 | +8 | field05: int = 1234567890 + | + = help: Replace with `...` + +ℹ Suggested fix +1 1 | field01: int = 0xFFFFFFFF +2 2 | field02: int = 0xFFFFFFFFF # Error: PYI054 +3 3 | field03: int = -0xFFFFFFFF +4 |-field04: int = -0xFFFFFFFFF # Error: PYI054 + 4 |+field04: int = -... # Error: PYI054 +5 5 | +6 6 | field05: int = 1234567890 +7 7 | field06: int = 12_456_890 + +PYI054.pyi:8:16: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | + 8 | field05: int = 1234567890 + 9 | field06: int = 12_456_890 +10 | field07: int = 12345678901 # Error: PYI054 + | ^^^^^^^^^^^ PYI054 +11 | field08: int = -1234567801 +12 | field09: int = -234_567_890 # Error: PYI054 + | + = help: Replace with `...` + +ℹ Suggested fix +5 5 | +6 6 | field05: int = 1234567890 +7 7 | field06: int = 12_456_890 +8 |-field07: int = 12345678901 # Error: PYI054 + 8 |+field07: int = ... # Error: PYI054 +9 9 | field08: int = -1234567801 +10 10 | field09: int = -234_567_890 # Error: PYI054 +11 11 | + +PYI054.pyi:10:17: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | +10 | field07: int = 12345678901 # Error: PYI054 +11 | field08: int = -1234567801 +12 | field09: int = -234_567_890 # Error: PYI054 + | ^^^^^^^^^^^ PYI054 +13 | +14 | field10: float = 123.456789 + | + = help: Replace with `...` + +ℹ Suggested fix +7 7 | field06: int = 12_456_890 +8 8 | field07: int = 12345678901 # Error: PYI054 +9 9 | field08: int = -1234567801 +10 |-field09: int = -234_567_890 # Error: PYI054 + 10 |+field09: int = -... # Error: PYI054 +11 11 | +12 12 | field10: float = 123.456789 +13 13 | field11: float = 123.4567890 # Error: PYI054 + +PYI054.pyi:13:18: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | +13 | field10: float = 123.456789 +14 | field11: float = 123.4567890 # Error: PYI054 + | ^^^^^^^^^^^ PYI054 +15 | field12: float = -123.456789 +16 | field13: float = -123.567_890 # Error: PYI054 + | + = help: Replace with `...` + +ℹ Suggested fix +10 10 | field09: int = -234_567_890 # Error: PYI054 +11 11 | +12 12 | field10: float = 123.456789 +13 |-field11: float = 123.4567890 # Error: PYI054 + 13 |+field11: float = ... # Error: PYI054 +14 14 | field12: float = -123.456789 +15 15 | field13: float = -123.567_890 # Error: PYI054 +16 16 | + +PYI054.pyi:15:19: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | +15 | field11: float = 123.4567890 # Error: PYI054 +16 | field12: float = -123.456789 +17 | field13: float = -123.567_890 # Error: PYI054 + | ^^^^^^^^^^^ PYI054 +18 | +19 | field14: complex = 1e1234567j + | + = help: Replace with `...` + +ℹ Suggested fix +12 12 | field10: float = 123.456789 +13 13 | field11: float = 123.4567890 # Error: PYI054 +14 14 | field12: float = -123.456789 +15 |-field13: float = -123.567_890 # Error: PYI054 + 15 |+field13: float = -... # Error: PYI054 +16 16 | +17 17 | field14: complex = 1e1234567j +18 18 | field15: complex = 1e12345678j # Error: PYI054 + +PYI054.pyi:18:20: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | +18 | field14: complex = 1e1234567j +19 | field15: complex = 1e12345678j # Error: PYI054 + | ^^^^^^^^^^^ PYI054 +20 | field16: complex = -1e1234567j +21 | field17: complex = 1e123456789j # Error: PYI054 + | + = help: Replace with `...` + +ℹ Suggested fix +15 15 | field13: float = -123.567_890 # Error: PYI054 +16 16 | +17 17 | field14: complex = 1e1234567j +18 |-field15: complex = 1e12345678j # Error: PYI054 + 18 |+field15: complex = ... # Error: PYI054 +19 19 | field16: complex = -1e1234567j +20 20 | field17: complex = 1e123456789j # Error: PYI054 + +PYI054.pyi:20:20: PYI054 [*] Numeric literals with a string representation longer than ten characters are not permitted + | +20 | field15: complex = 1e12345678j # Error: PYI054 +21 | field16: complex = -1e1234567j +22 | field17: complex = 1e123456789j # Error: PYI054 + | ^^^^^^^^^^^^ PYI054 + | + = help: Replace with `...` + +ℹ Suggested fix +17 17 | field14: complex = 1e1234567j +18 18 | field15: complex = 1e12345678j # Error: PYI054 +19 19 | field16: complex = -1e1234567j +20 |-field17: complex = 1e123456789j # Error: PYI054 + 20 |+field17: complex = ... # Error: PYI054 + + diff --git a/ruff.schema.json b/ruff.schema.json index 57be720b3937d..d4a044b393b01 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -2252,6 +2252,7 @@ "PYI05", "PYI052", "PYI053", + "PYI054", "Q", "Q0", "Q00",