From a3aeec63774a1855ab1ac83b549c1443894343d9 Mon Sep 17 00:00:00 2001 From: Florian Best Date: Fri, 10 Mar 2023 23:36:38 +0100 Subject: [PATCH] docs(pycodestyle): document rules (#3407) --- .../pycodestyle/rules/ambiguous_class_name.rs | 18 +++ .../rules/ambiguous_function_name.rs | 18 +++ .../rules/ambiguous_variable_name.rs | 21 +++ .../pycodestyle/rules/compound_statements.rs | 56 +++++++ .../pycodestyle/rules/doc_line_too_long.rs | 21 +++ .../src/rules/pycodestyle/rules/errors.rs | 2 + .../rules/extraneous_whitespace.rs | 64 ++++++++ .../src/rules/pycodestyle/rules/imports.rs | 48 ++++++ .../rules/pycodestyle/rules/indentation.rs | 149 +++++++++++++++++- .../rules/invalid_escape_sequence.rs | 15 ++ .../pycodestyle/rules/lambda_assignment.rs | 24 +++ .../rules/pycodestyle/rules/line_too_long.rs | 18 +++ .../pycodestyle/rules/literal_comparisons.rs | 41 +++++ .../rules/mixed_spaces_and_tabs.rs | 20 +++ .../rules/no_newline_at_end_of_file.rs | 16 ++ .../src/rules/pycodestyle/rules/not_tests.rs | 38 +++++ .../rules/space_around_operator.rs | 76 +++++++++ .../pycodestyle/rules/trailing_whitespace.rs | 39 +++++ .../pycodestyle/rules/type_comparison.rs | 18 +++ .../rules/whitespace_around_keywords.rs | 63 ++++++++ .../rules/whitespace_before_comment.rs | 89 +++++++++++ 21 files changed, 853 insertions(+), 1 deletion(-) diff --git a/crates/ruff/src/rules/pycodestyle/rules/ambiguous_class_name.rs b/crates/ruff/src/rules/pycodestyle/rules/ambiguous_class_name.rs index d59eea6185..3a1d75f13a 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/ambiguous_class_name.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/ambiguous_class_name.rs @@ -4,6 +4,24 @@ use ruff_python_ast::types::Range; use crate::rules::pycodestyle::helpers::is_ambiguous_name; +/// ## What it does +/// Checks for the use of the characters 'l', 'O', or 'I' as class names. +/// +/// ## Why is this bad? +/// In some fonts, these characters are indistinguishable from the +/// numerals one and zero. When tempted to use 'l', use 'L' instead. +/// +/// ## Example +/// ```python +/// class I(object): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// class Integer(object): +/// ... +/// ``` #[violation] pub struct AmbiguousClassName(pub String); diff --git a/crates/ruff/src/rules/pycodestyle/rules/ambiguous_function_name.rs b/crates/ruff/src/rules/pycodestyle/rules/ambiguous_function_name.rs index 64753829da..b3656bdffc 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/ambiguous_function_name.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/ambiguous_function_name.rs @@ -4,6 +4,24 @@ use ruff_python_ast::types::Range; use crate::rules::pycodestyle::helpers::is_ambiguous_name; +/// ## What it does +/// Checks for the use of the characters 'l', 'O', or 'I' as function names. +/// +/// ## Why is this bad? +/// In some fonts, these characters are indistinguishable from the +/// numerals one and zero. When tempted to use 'l', use 'L' instead. +/// +/// ## Example +/// ```python +/// def l(x): +/// ... +/// ``` +/// +/// Use instead: +/// ```python +/// def long_name(x): +/// ... +/// ``` #[violation] pub struct AmbiguousFunctionName(pub String); diff --git a/crates/ruff/src/rules/pycodestyle/rules/ambiguous_variable_name.rs b/crates/ruff/src/rules/pycodestyle/rules/ambiguous_variable_name.rs index a6f807d1a8..bdfe813106 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/ambiguous_variable_name.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/ambiguous_variable_name.rs @@ -4,6 +4,27 @@ use ruff_python_ast::types::Range; use crate::rules::pycodestyle::helpers::is_ambiguous_name; +/// ## What it does +/// Checks for the use of the characters 'l', 'O', or 'I' as variable names. +/// +/// ## Why is this bad? +/// In some fonts, these characters are indistinguishable from the +/// numerals one and zero. When tempted to use 'l', use 'L' instead. +/// +/// ## Example +/// ```python +/// l = 0 +/// O = 123 +/// I = 42 +/// ``` +/// +/// Use instead: +/// ```python +/// L = 0 +/// o = 123 +/// i = 42 +/// ``` + #[violation] pub struct AmbiguousVariableName(pub String); diff --git a/crates/ruff/src/rules/pycodestyle/rules/compound_statements.rs b/crates/ruff/src/rules/pycodestyle/rules/compound_statements.rs index 37d90a9b5f..e8dfb09a3f 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/compound_statements.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/compound_statements.rs @@ -9,6 +9,25 @@ use ruff_python_ast::types::Range; use crate::registry::Rule; use crate::settings::{flags, Settings}; +/// ## What it does +/// Checks for compound statements (multiple statements on the same line). +/// +/// ## Why is this bad? +/// Per PEP 8, "compound statements are generally discouraged". +/// +/// ## Example +/// ```python +/// if foo == 'blah': do_blah_thing() +/// ``` +/// +/// Use instead: +/// ```python +/// if foo == 'blah': +/// do_blah_thing() +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#other-recommendations) #[violation] pub struct MultipleStatementsOnOneLineColon; @@ -19,6 +38,27 @@ impl Violation for MultipleStatementsOnOneLineColon { } } +/// ## What it does +/// Checks for multiline statements on one line. +/// +/// ## Why is this bad? +/// Per PEP 8, including multi-clause statements on the same line is +/// discouraged. +/// +/// ## Example +/// ```python +/// do_one(); do_two(); do_three() +/// ``` +/// +/// Use instead: +/// ```python +/// do_one() +/// do_two() +/// do_three() +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#other-recommendations) #[violation] pub struct MultipleStatementsOnOneLineSemicolon; @@ -29,6 +69,21 @@ impl Violation for MultipleStatementsOnOneLineSemicolon { } } +/// ## What it does +/// Checks for statements that end with an unnecessary semicolon. +/// +/// ## Why is this bad? +/// A trailing semicolon is unnecessary and should be removed. +/// +/// ## Example +/// ```python +/// do_four(); # useless semicolon +/// ``` +/// +/// Use instead: +/// ```python +/// do_four() +/// ``` #[violation] pub struct UselessSemicolon; @@ -43,6 +98,7 @@ impl AlwaysAutofixableViolation for UselessSemicolon { } } +/// E701, E702, E703 pub fn compound_statements( lxr: &[LexResult], settings: &Settings, diff --git a/crates/ruff/src/rules/pycodestyle/rules/doc_line_too_long.rs b/crates/ruff/src/rules/pycodestyle/rules/doc_line_too_long.rs index 09b7e545e6..a608640193 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/doc_line_too_long.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/doc_line_too_long.rs @@ -7,6 +7,27 @@ use ruff_python_ast::types::Range; use crate::rules::pycodestyle::helpers::is_overlong; use crate::settings::Settings; +/// ## What it does +/// Checks for doc lines that exceed the specified maximum character length. +/// +/// ## Why is this bad? +/// For flowing long blocks of text (docstrings or comments), overlong lines +/// can hurt readability. +/// +/// ## Example +/// ```python +/// def function(x): +/// """Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis auctor purus ut ex fermentum, at maximus est hendrerit.""" +/// ``` +/// +/// Use instead: +/// ```python +/// def function(x): +/// """ +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. +/// Duis auctor purus ut ex fermentum, at maximus est hendrerit. +/// """ +/// ``` #[violation] pub struct DocLineTooLong(pub usize, pub usize); diff --git a/crates/ruff/src/rules/pycodestyle/rules/errors.rs b/crates/ruff/src/rules/pycodestyle/rules/errors.rs index ab1b277b2c..291fd5fa63 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/errors.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/errors.rs @@ -9,6 +9,7 @@ pub struct IOError { pub message: String, } +/// E902 impl Violation for IOError { #[derive_message_formats] fn message(&self) -> String { @@ -30,6 +31,7 @@ impl Violation for SyntaxError { } } +/// E901 pub fn syntax_error(diagnostics: &mut Vec, parse_error: &ParseError) { diagnostics.push(Diagnostic::new( SyntaxError { diff --git a/crates/ruff/src/rules/pycodestyle/rules/extraneous_whitespace.rs b/crates/ruff/src/rules/pycodestyle/rules/extraneous_whitespace.rs index 1f30c456ea..6cf1557457 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/extraneous_whitespace.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/extraneous_whitespace.rs @@ -7,6 +7,28 @@ use ruff_diagnostics::DiagnosticKind; use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +/// ## What it does +/// Checks for the use of extraneous whitespace after "(". +/// +/// ## Why is this bad? +/// PEP 8 recommends the omission of whitespace in the following cases: +/// - "Immediately inside parentheses, brackets or braces." +/// - "Immediately before a comma, semicolon, or colon." +/// +/// ## Example +/// ```python +/// spam( ham[1], {eggs: 2}) +/// spam(ham[ 1], {eggs: 2}) +/// spam(ham[1], { eggs: 2}) +/// ``` +/// +/// Use instead: +/// ```python +/// spam(ham[1], {eggs: 2}) +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#pet-peeves) #[violation] pub struct WhitespaceAfterOpenBracket; @@ -17,6 +39,28 @@ impl Violation for WhitespaceAfterOpenBracket { } } +/// ## What it does +/// Checks for the use of extraneous whitespace before ")". +/// +/// ## Why is this bad? +/// PEP 8 recommends the omission of whitespace in the following cases: +/// - "Immediately inside parentheses, brackets or braces." +/// - "Immediately before a comma, semicolon, or colon." +/// +/// ## Example +/// ```python +/// spam(ham[1], {eggs: 2} ) +/// spam(ham[1 ], {eggs: 2}) +/// spam(ham[1], {eggs: 2 }) +/// ``` +/// +/// Use instead: +/// ```python +/// spam(ham[1], {eggs: 2}) +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#pet-peeves) #[violation] pub struct WhitespaceBeforeCloseBracket; @@ -27,6 +71,26 @@ impl Violation for WhitespaceBeforeCloseBracket { } } +/// ## What it does +/// Checks for the use of extraneous whitespace before ",", ";" or ":". +/// +/// ## Why is this bad? +/// PEP 8 recommends the omission of whitespace in the following cases: +/// - "Immediately inside parentheses, brackets or braces." +/// - "Immediately before a comma, semicolon, or colon." +/// +/// ## Example +/// ```python +/// if x == 4: print(x, y); x, y = y , x +/// ``` +/// +/// Use instead: +/// ```python +/// if x == 4: print(x, y); x, y = y, x +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#pet-peeves) #[violation] pub struct WhitespaceBeforePunctuation; diff --git a/crates/ruff/src/rules/pycodestyle/rules/imports.rs b/crates/ruff/src/rules/pycodestyle/rules/imports.rs index 99f8de9106..e6c34d4caf 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/imports.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/imports.rs @@ -6,6 +6,25 @@ use ruff_python_ast::types::Range; use crate::checkers::ast::Checker; +/// ## What it does +/// Check for multiple imports on one line. +/// +/// ## Why is this bad? +/// Per PEP 8, "imports should usually be on separate lines." +/// +/// ## Example +/// ```python +/// import sys, os +/// ``` +/// +/// Use instead: +/// ```python +/// import os +/// import sys +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#imports) #[violation] pub struct MultipleImportsOnOneLine; @@ -16,6 +35,33 @@ impl Violation for MultipleImportsOnOneLine { } } +/// ## What it does +/// Checks for imports that are not at the top of the file. +/// +/// ## Why is this bad? +/// Per PEP 8, "imports are always put at the top of the file, just after any +/// module comments and docstrings, and before module globals and constants." +/// +/// ## Example +/// ```python +/// 'One string' +/// "Two string" +/// a = 1 +/// import os +/// from sys import x +/// ``` +/// +/// Use instead: +/// ```python +/// import os +/// from sys import x +/// 'One string' +/// "Two string" +/// a = 1 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#imports) #[violation] pub struct ModuleImportNotAtTopOfFile; @@ -26,6 +72,7 @@ impl Violation for ModuleImportNotAtTopOfFile { } } +/// E401 pub fn multiple_imports_on_one_line(checker: &mut Checker, stmt: &Stmt, names: &[Alias]) { if names.len() > 1 { checker @@ -34,6 +81,7 @@ pub fn multiple_imports_on_one_line(checker: &mut Checker, stmt: &Stmt, names: & } } +/// E402 pub fn module_import_not_at_top_of_file(checker: &mut Checker, stmt: &Stmt) { if checker.ctx.seen_import_boundary && stmt.location.column() == 0 { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/pycodestyle/rules/indentation.rs b/crates/ruff/src/rules/pycodestyle/rules/indentation.rs index d1e9d13bfb..bed6ad5448 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/indentation.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/indentation.rs @@ -6,6 +6,26 @@ use ruff_macros::{derive_message_formats, violation}; use crate::rules::pycodestyle::logical_lines::LogicalLine; +/// ## What it does +/// Checks for indentation with a non-multiple of 4 spaces. +/// +/// ## Why is this bad? +/// Per PEP 8, 4 spaces per indentation level should be preferred. +/// +/// ## Example +/// ```python +/// if True: +/// a = 1 +/// ``` +/// +/// Use instead: +/// ```python +/// if True: +/// a = 1 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#indentation) #[violation] pub struct IndentationWithInvalidMultiple { pub indent_size: usize, @@ -19,6 +39,26 @@ impl Violation for IndentationWithInvalidMultiple { } } +/// ## What it does +/// Checks for indentation of comments with a non-multiple of 4 spaces. +/// +/// ## Why is this bad? +/// Per PEP 8, 4 spaces per indentation level should be preferred. +/// +/// ## Example +/// ```python +/// if True: +/// # a = 1 +/// ``` +/// +/// Use instead: +/// ```python +/// if True: +/// # a = 1 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#indentation) #[violation] pub struct IndentationWithInvalidMultipleComment { pub indent_size: usize, @@ -32,6 +72,28 @@ impl Violation for IndentationWithInvalidMultipleComment { } } +/// ## What it does +/// Checks for indented blocks that are lacking indentation. +/// +/// ## Why is this bad? +/// All indented blocks should be indented; otherwise, they are not valid +/// Python syntax. +/// +/// ## Example +/// ```python +/// for item in items: +/// pass +/// +/// ``` +/// +/// Use instead: +/// ```python +/// for item in items: +/// pass +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#indentation) #[violation] pub struct NoIndentedBlock; @@ -42,6 +104,29 @@ impl Violation for NoIndentedBlock { } } +/// ## What it does +/// Checks for comments in a code blocks that are lacking indentation. +/// +/// ## Why is this bad? +/// Comments within an indented block should themselves be indented, to +/// indicate that they are part of the block. +/// +/// ## Example +/// ```python +/// for item in items: +/// # Hi +/// pass +/// ``` +/// +/// Use instead: +/// ```python +/// for item in items: +/// # Hi +/// pass +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#indentation) #[violation] pub struct NoIndentedBlockComment; @@ -52,6 +137,26 @@ impl Violation for NoIndentedBlockComment { } } +/// ## What it does +/// Checks for unexpected indentation. +/// +/// ## Why is this bad? +/// Indentation outside of a code block is not valid Python syntax. +/// +/// ## Example +/// ```python +/// a = 1 +/// b = 2 +/// ``` +/// +/// Use instead: +/// ```python +/// a = 1 +/// b = 2 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#indentation) #[violation] pub struct UnexpectedIndentation; @@ -62,6 +167,26 @@ impl Violation for UnexpectedIndentation { } } +/// ## What it does +/// Checks for unexpected indentation of comment. +/// +/// ## Why is this bad? +/// Comments should match the indentation of the containing code block. +/// +/// ## Example +/// ```python +/// a = 1 +/// # b = 2 +/// ``` +/// +/// Use instead: +/// ```python +/// a = 1 +/// # b = 2 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#indentation) #[violation] pub struct UnexpectedIndentationComment; @@ -72,6 +197,28 @@ impl Violation for UnexpectedIndentationComment { } } +/// ## What it does +/// Checks for over-indented code. +/// +/// ## Why is this bad? +/// Per PEP 8, 4 spaces per indentation level should be preferred. Increased +/// indentation can lead to inconsistent formatting, which can hurt +/// readability. +/// +/// ## Example +/// ```python +/// for item in items: +/// pass +/// ``` +/// +/// Use instead: +/// ```python +/// for item in items: +/// pass +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#indentation) #[violation] pub struct OverIndented; @@ -82,7 +229,7 @@ impl Violation for OverIndented { } } -/// E111 +/// E111, E114, E112, E113, E115, E116, E117 #[cfg(feature = "logical_lines")] pub fn indentation( logical_line: &LogicalLine, diff --git a/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs b/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs index 4e5c4634b8..dd79f339d3 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/invalid_escape_sequence.rs @@ -7,6 +7,21 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::source_code::Locator; use ruff_python_ast::types::Range; +/// ## What it does +/// Checks for invalid escape sequences. +/// +/// ## Why is this bad? +/// Invalid escape sequences are deprecated in Python 3.6. +/// +/// ## Example +/// ```python +/// regex = '\.png$' +/// ``` +/// +/// Use instead: +/// ```python +/// regex = r'\.png$' +/// ``` #[violation] pub struct InvalidEscapeSequence(pub char); diff --git a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs index 893e6baf91..335a9dba13 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs @@ -10,6 +10,30 @@ use ruff_python_ast::whitespace::leading_space; use crate::checkers::ast::Checker; use crate::registry::AsRule; +/// ## What it does +/// Checks for lambda expressions which are assigned to a variable. +/// +/// ## Why is this bad? +/// Per PEP 8, you should "Always use a def statement instead of an assignment +/// statement that binds a lambda expression directly to an identifier." +/// +/// Using a `def` statement leads to better tracebacks, and the assignment +/// itself negates the primary benefit of using a `lambda` expression (i.e., +/// that it can be embedded inside another expression). +/// +/// ## Example +/// ```python +/// f = lambda x: 2*x +/// ``` +/// +/// Use instead: +/// ```python +/// def f(x): +/// return 2 * x +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#programming-recommendations) #[violation] pub struct LambdaAssignment { pub name: String, diff --git a/crates/ruff/src/rules/pycodestyle/rules/line_too_long.rs b/crates/ruff/src/rules/pycodestyle/rules/line_too_long.rs index 66c8142b17..669215c062 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/line_too_long.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/line_too_long.rs @@ -7,6 +7,24 @@ use ruff_python_ast::types::Range; use crate::rules::pycodestyle::helpers::is_overlong; use crate::settings::Settings; +/// ## What it does +/// Checks for lines that exceed the specified maximum character length. +/// +/// ## Why is this bad? +/// Overlong lines can hurt readability. +/// +/// ## Example +/// ```python +/// my_function(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) +/// ``` +/// +/// Use instead: +/// ```python +/// my_function( +/// param1, param2, param3, param4, param5, +/// param6, param7, param8, param9, param10 +/// ) +/// ``` #[violation] pub struct LineTooLong(pub usize, pub usize); diff --git a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs index c213a2c639..e8dbfbc40d 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/literal_comparisons.rs @@ -28,6 +28,26 @@ impl From<&Cmpop> for EqCmpop { } } +/// ## What it does +/// Checks for comparisons to `None` which are not using the `is` operator. +/// +/// ## Why is this bad? +/// Per PEP 8, "Comparisons to singletons like None should always be done with +/// is or is not, never the equality operators." +/// +/// ## Example +/// ```python +/// if arg != None: +/// if None == arg: +/// ``` +/// +/// Use instead: +/// ```python +/// if arg is not None: +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#programming-recommendations) #[violation] pub struct NoneComparison(pub EqCmpop); @@ -50,6 +70,27 @@ impl AlwaysAutofixableViolation for NoneComparison { } } +/// ## What it does +/// Checks for comparisons to booleans which are not using the `is` operator. +/// +/// ## Why is this bad? +/// Per PEP 8, "Comparisons to singletons like None should always be done with +/// is or is not, never the equality operators." +/// +/// ## Example +/// ```python +/// if arg == True: +/// if False == arg: +/// ``` +/// +/// Use instead: +/// ```python +/// if arg is True: +/// if arg is False: +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#programming-recommendations) #[violation] pub struct TrueFalseComparison(pub bool, pub EqCmpop); diff --git a/crates/ruff/src/rules/pycodestyle/rules/mixed_spaces_and_tabs.rs b/crates/ruff/src/rules/pycodestyle/rules/mixed_spaces_and_tabs.rs index bf178fb6f8..7e12a5e0d9 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/mixed_spaces_and_tabs.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/mixed_spaces_and_tabs.rs @@ -5,6 +5,26 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::types::Range; use ruff_python_ast::whitespace::leading_space; +/// ## What it does +/// Checks for mixed tabs and spaces in indentation. +/// +/// ## Why is this bad? +/// Never mix tabs and spaces. +/// +/// The most popular way of indenting Python is with spaces only. The +/// second-most popular way is with tabs only. Code indented with a +/// mixture of tabs and spaces should be converted to using spaces +/// exclusively. +/// +/// ## Example +/// ```python +/// if a == 0:\n a = 1\n\tb = 1 +/// ``` +/// +/// Use instead: +/// ```python +/// if a == 0:\n a = 1\n b = 1 +/// ``` #[violation] pub struct MixedSpacesAndTabs; diff --git a/crates/ruff/src/rules/pycodestyle/rules/no_newline_at_end_of_file.rs b/crates/ruff/src/rules/pycodestyle/rules/no_newline_at_end_of_file.rs index 45a3589257..e5411cc53c 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/no_newline_at_end_of_file.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/no_newline_at_end_of_file.rs @@ -5,6 +5,22 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::source_code::Stylist; use ruff_python_ast::types::Range; +/// ## What it does +/// Checks for files missing a new line at the end of the file. +/// +/// ## Why is this bad? +/// Trailing blank lines are superfluous. +/// However the last line should end with a new line. +/// +/// ## Example +/// ```python +/// spam(1) +/// ``` +/// +/// Use instead: +/// ```python +/// spam(1)\n +/// ``` #[violation] pub struct NoNewLineAtEndOfFile; diff --git a/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs b/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs index 3ca62d4e9c..394117a19d 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/not_tests.rs @@ -8,6 +8,25 @@ use crate::checkers::ast::Checker; use crate::registry::AsRule; use crate::rules::pycodestyle::helpers::compare; +/// ## What it does +/// Checks for negative comparison using `not {foo} in {bar}`. +/// +/// ## Why is this bad? +/// Negative comparison should be done using `not in`. +/// +/// ## Example +/// ```python +/// Z = not X in Y +/// if not X.B in Y:\n pass +/// +/// ``` +/// +/// Use instead: +/// ```python +/// if x not in y:\n pass +/// assert (X in Y or X is Z) +/// +/// ``` #[violation] pub struct NotInTest; @@ -22,6 +41,25 @@ impl AlwaysAutofixableViolation for NotInTest { } } +/// ## What it does +/// Checks for negative comparison using `not {foo} is {bar}`. +/// +/// ## Why is this bad? +/// Negative comparison should be done using `is not`. +/// +/// ## Example +/// ```python +/// if not X is Y: +/// pass +/// Z = not X.B is Y +/// ``` +/// +/// Use instead: +/// ```python +/// if not (X in Y): +/// pass +/// zz = x is not y +/// ``` #[violation] pub struct NotIsTest; diff --git a/crates/ruff/src/rules/pycodestyle/rules/space_around_operator.rs b/crates/ruff/src/rules/pycodestyle/rules/space_around_operator.rs index 00f861a82e..fedc6b69e2 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/space_around_operator.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/space_around_operator.rs @@ -7,6 +7,25 @@ use ruff_diagnostics::DiagnosticKind; use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +/// ## What it does +/// Checks for extraneous tabs before an operator. +/// +/// ## Why is this bad? +/// Per PEP 8, operators should be surrounded by at most a single space on either +/// side. +/// +/// ## Example +/// ```python +/// a = 4\t+ 5 +/// ``` +/// +/// Use instead: +/// ```python +/// a = 12 + 3 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements) #[violation] pub struct TabBeforeOperator; @@ -17,6 +36,25 @@ impl Violation for TabBeforeOperator { } } +/// ## What it does +/// Checks for extraneous whitespace before an operator. +/// +/// ## Why is this bad? +/// Per PEP 8, operators should be surrounded by at most a single space on either +/// side. +/// +/// ## Example +/// ```python +/// a = 4 + 5 +/// ``` +/// +/// Use instead: +/// ```python +/// a = 12 + 3 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements) #[violation] pub struct MultipleSpacesBeforeOperator; @@ -27,6 +65,25 @@ impl Violation for MultipleSpacesBeforeOperator { } } +/// ## What it does +/// Checks for extraneous tabs after an operator. +/// +/// ## Why is this bad? +/// Per PEP 8, operators should be surrounded by at most a single space on either +/// side. +/// +/// ## Example +/// ```python +/// a = 4 +\t5 +/// ``` +/// +/// Use instead: +/// ```python +/// a = 12 + 3 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements) #[violation] pub struct TabAfterOperator; @@ -37,6 +94,25 @@ impl Violation for TabAfterOperator { } } +/// ## What it does +/// Checks for extraneous whitespace after an operator. +/// +/// ## Why is this bad? +/// Per PEP 8, operators should be surrounded by at most a single space on either +/// side. +/// +/// ## Example +/// ```python +/// a = 4 + 5 +/// ``` +/// +/// Use instead: +/// ```python +/// a = 12 + 3 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#whitespace-in-expressions-and-statements) #[violation] pub struct MultipleSpacesAfterOperator; diff --git a/crates/ruff/src/rules/pycodestyle/rules/trailing_whitespace.rs b/crates/ruff/src/rules/pycodestyle/rules/trailing_whitespace.rs index 6c9338c350..d6eeeb9785 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/trailing_whitespace.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/trailing_whitespace.rs @@ -7,6 +7,25 @@ use ruff_python_ast::types::Range; use crate::registry::Rule; use crate::settings::{flags, Settings}; +/// ## What it does +/// Checks for superfluous trailing whitespace. +/// +/// ## Why is this bad? +/// Per PEP 8, "avoid trailing whitespace anywhere. Because it’s usually +/// invisible, it can be confusing" +/// +/// ## Example +/// ```python +/// spam(1) \n# +/// ``` +/// +/// Use instead: +/// ```python +/// spam(1)\n# +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#other-recommendations) #[violation] pub struct TrailingWhitespace; @@ -21,6 +40,26 @@ impl AlwaysAutofixableViolation for TrailingWhitespace { } } +/// ## What it does +/// Checks for superfluous whitespace in blank lines. +/// +/// ## Why is this bad? +/// Per PEP 8, "avoid trailing whitespace anywhere. Because it’s usually +/// invisible, it can be confusing" +/// +/// ## Example +/// ```python +/// class Foo(object):\n \n bang = 12 +/// +/// ``` +/// +/// Use instead: +/// ```python +/// class Foo(object):\n\n bang = 12 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#other-recommendations) #[violation] pub struct BlankLineContainsWhitespace; diff --git a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs index 002fbc48eb..fde3b00735 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs @@ -5,6 +5,24 @@ use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::types::Range; +/// ## What it does +/// Checks for object type comparisons without using isinstance(). +/// +/// ## Why is this bad? +/// Do not compare types directly. +/// When checking if an object is a instance of a certain type, keep in mind that it might +/// be subclassed. E.g. `bool` inherits from `int` or `Exception` inherits from `BaseException`. +/// +/// ## Example +/// ```python +/// if type(obj) is type(1): +/// ``` +/// +/// Use instead: +/// ```python +/// if isinstance(obj, int): +/// if type(a1) is type(b1): +/// ``` #[violation] pub struct TypeComparison; diff --git a/crates/ruff/src/rules/pycodestyle/rules/whitespace_around_keywords.rs b/crates/ruff/src/rules/pycodestyle/rules/whitespace_around_keywords.rs index 4dfa6bc289..f7c056b917 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/whitespace_around_keywords.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/whitespace_around_keywords.rs @@ -7,6 +7,21 @@ use ruff_diagnostics::DiagnosticKind; use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; +/// ## What it does +/// Checks for extraneous whitespace after keywords. +/// +/// ## Why is this bad? +/// +/// +/// ## Example +/// ```python +/// True and False +/// ``` +/// +/// Use instead: +/// ```python +/// True and False +/// ``` #[violation] pub struct MultipleSpacesAfterKeyword; @@ -17,6 +32,22 @@ impl Violation for MultipleSpacesAfterKeyword { } } +/// ## What it does +/// Checks for extraneous whitespace before keywords. +/// +/// ## Why is this bad? +/// +/// +/// ## Example +/// ```python +/// True and False +/// +/// ``` +/// +/// Use instead: +/// ```python +/// True and False +/// ``` #[violation] pub struct MultipleSpacesBeforeKeyword; @@ -27,6 +58,22 @@ impl Violation for MultipleSpacesBeforeKeyword { } } +/// ## What it does +/// Checks for extraneous tabs after keywords. +/// +/// ## Why is this bad? +/// +/// +/// ## Example +/// ```python +/// True and\tFalse +/// +/// ``` +/// +/// Use instead: +/// ```python +/// True and False +/// ``` #[violation] pub struct TabAfterKeyword; @@ -37,6 +84,22 @@ impl Violation for TabAfterKeyword { } } +/// ## What it does +/// Checks for extraneous tabs before keywords. +/// +/// ## Why is this bad? +/// +/// +/// ## Example +/// ```python +/// True\tand False +/// +/// ``` +/// +/// Use instead: +/// ```python +/// True and False +/// ``` #[violation] pub struct TabBeforeKeyword; diff --git a/crates/ruff/src/rules/pycodestyle/rules/whitespace_before_comment.rs b/crates/ruff/src/rules/pycodestyle/rules/whitespace_before_comment.rs index f3614803c0..293ebcd8e5 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/whitespace_before_comment.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/whitespace_before_comment.rs @@ -9,6 +9,25 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::source_code::Locator; use ruff_python_ast::types::Range; +/// ## What it does +/// Checks if inline comments are separated by at least two spaces. +/// +/// ## Why is this bad? +/// An inline comment is a comment on the same line as a statement. +/// +/// Per PEP8, inline comments should be separated by at least two spaces from +/// the preceding statement. +/// +/// ## Example +/// ```python +/// x = x + 1 # Increment x +/// ``` +/// +/// Use instead: +/// ```python +/// x = x + 1 # Increment x +/// x = x + 1 # Increment x +/// ``` #[violation] pub struct TooFewSpacesBeforeInlineComment; @@ -19,6 +38,29 @@ impl Violation for TooFewSpacesBeforeInlineComment { } } +/// ## What it does +/// Checks if one space is used after inline comments. +/// +/// ## Why is this bad? +/// An inline comment is a comment on the same line as a statement. +/// +/// Per PEP8, inline comments should start with a # and a single space. +/// +/// ## Example +/// ```python +/// x = x + 1 #Increment x +/// x = x + 1 # Increment x +/// x = x + 1 # \xa0Increment x +/// ``` +/// +/// Use instead: +/// ```python +/// x = x + 1 # Increment x +/// x = x + 1 # Increment x +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#comments) #[violation] pub struct NoSpaceAfterInlineComment; @@ -29,6 +71,29 @@ impl Violation for NoSpaceAfterInlineComment { } } +/// ## What it does +/// Checks if one space is used after block comments. +/// +/// ## Why is this bad? +/// Per PEP8, "Block comments generally consist of one or more paragraphs built +/// out of complete sentences, with each sentence ending in a period." +/// +/// Block comments should start with a # and a single space. +/// +/// ## Example +/// ```python +/// #Block comment +/// ``` +/// +/// Use instead: +/// ```python +/// # Block comments: +/// # - Block comment list +/// # \xa0- Block comment list +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#comments) #[violation] pub struct NoSpaceAfterBlockComment; @@ -39,6 +104,30 @@ impl Violation for NoSpaceAfterBlockComment { } } +/// ## What it does +/// Checks if block comments start with a single "#". +/// +/// ## Why is this bad? +/// Per PEP8, "Block comments generally consist of one or more paragraphs built +/// out of complete sentences, with each sentence ending in a period." +/// +/// Each line of a block comment should start with a # and a single space. +/// +/// ## Example +/// ```python +/// ### Block comment +/// +/// ``` +/// +/// Use instead: +/// ```python +/// # Block comments: +/// # - Block comment list +/// # \xa0- Block comment list +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#comments) #[violation] pub struct MultipleLeadingHashesForBlockComment;