Add PLE rule docs (#4437)

This commit is contained in:
Tom Kuson 2023-05-15 20:48:18 +01:00 committed by GitHub
parent 8f3f8d3e0b
commit 838ba1ca3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 207 additions and 0 deletions

View file

@ -6,6 +6,33 @@ use ruff_python_semantic::scope::{FunctionDef, ScopeKind};
use crate::checkers::ast::Checker;
/// ## What it does
/// Checks for usages of `await` outside of `async` functions.
///
/// ## Why is this bad?
/// Using `await` outside of an `async` function is a syntax error.
///
/// ## Example
/// ```python
/// import asyncio
///
///
/// def foo():
/// await asyncio.sleep(1)
/// ```
///
/// Use instead:
/// ```python
/// import asyncio
///
///
/// async def foo():
/// await asyncio.sleep(1)
/// ```
///
/// ## References
/// - [Python documentation](https://docs.python.org/3/reference/expressions.html#await)
/// - [PEP 492](https://peps.python.org/pep-0492/#await-expression)
#[violation]
pub struct AwaitOutsideAsync;

View file

@ -9,6 +9,26 @@ use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker;
use crate::settings::types::PythonVersion;
/// ## What it does
/// Checks duplicate characters in `str#strip` calls.
///
/// ## Why is this bad?
/// All characters in `str#strip` calls are removed from both the leading and
/// trailing ends of the string. Including duplicate characters in the call
/// is redundant and often indicative of a mistake.
///
/// ## Example
/// ```python
/// "bar foo baz".strip("bar baz ") # "foo"
/// ```
///
/// Use instead:
/// ```python
/// "bar foo baz".strip("abrz ") # "foo"
/// ```
///
/// ## References
/// - [Python documentation](https://docs.python.org/3/library/stdtypes.html?highlight=strip#str.strip)
#[violation]
pub struct BadStrStripCall {
strip: StripKind,

View file

@ -22,6 +22,25 @@ const BIDI_UNICODE: [char; 10] = [
// to hide code
];
/// ## What it does
/// Checks for bidirectional unicode characters.
///
/// ## Why is this bad?
/// The interaction between bidirectional unicode characters and the
/// surrounding code can be surprising to those that are unfamiliar
/// with right-to-left writing systems.
///
/// In some cases, bidirectional unicode characters can also be used to
/// obfuscate code and introduce or mask security vulnerabilities.
///
/// ## Example
/// ```python
/// s = "א" * 100 # "א" is assigned
/// print(s) # prints a 100-character string
/// ```
///
/// ## References
/// - [PEP 672](https://peps.python.org/pep-0672/#bidirectional-text)
#[violation]
pub struct BidirectionalUnicode;

View file

@ -3,6 +3,28 @@ use rustpython_parser::ast::Expr;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
/// ## What it does
/// Checks for invalid assignments to `__all__`.
///
/// ## Why is this bad?
/// In Python, `__all__` should contain a sequence of strings that represent
/// the names of all "public" symbols exported by a module.
///
/// Assigning anything other than a `tuple` or `list` of strings to `__all__`
/// is invalid.
///
/// ## Example
/// ```python
/// __all__ = "Foo"
/// ```
///
/// Use instead:
/// ```python
/// __all__ = ("Foo",)
/// ```
///
/// ## References
/// - [Python documentation](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement)
#[violation]
pub struct InvalidAllFormat;

View file

@ -3,6 +3,28 @@ use rustpython_parser::ast::Expr;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
/// ## What it does
/// Checks for the inclusion of invalid objects in `__all__`.
///
/// ## Why is this bad?
/// In Python, `__all__` should contain a sequence of strings that represent
/// the names of all "public" symbols exported by a module.
///
/// Assigning anything other than a `tuple` or `list` of strings to `__all__`
/// is invalid.
///
/// ## Example
/// ```python
/// __all__ = [Foo, 1, None]
/// ```
///
/// Use instead:
/// ```python
/// __all__ = ["Foo", "Bar", "Baz"]
/// ```
///
/// ## References
/// - [Python documentation](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement)
#[violation]
pub struct InvalidAllObject;

View file

@ -7,6 +7,39 @@ use ruff_python_semantic::scope::ScopeKind;
use crate::checkers::ast::Checker;
/// ## What it does
/// Checks for usages of names that are declared as `global` prior to the
/// relevant `global` declaration.
///
/// ## Why is this bad?
/// The `global` declaration applies to the entire scope. Using a name that's
/// declared as `global` in a given scope prior to the relevant `global`
/// declaration is a syntax error.
///
/// ## Example
/// ```python
/// counter = 1
///
///
/// def increment():
/// print(f"Adding 1 to {counter}")
/// global counter
/// counter += 1
/// ```
///
/// Use instead:
/// ```python
/// counter = 1
///
///
/// def increment():
/// global counter
/// print(f"Adding 1 to {counter}")
/// counter += 1
/// ```
///
/// ## References
/// - [Python documentation](https://docs.python.org/3/reference/simple_stmts.html#the-global-statement)
#[violation]
pub struct LoadBeforeGlobalDeclaration {
name: String,

View file

@ -1,6 +1,33 @@
use ruff_diagnostics::Violation;
use ruff_macros::{derive_message_formats, violation};
/// ## What it does
/// Checks for `nonlocal` names without bindings.
///
/// ## Why is this bad?
/// `nonlocal` names must be bound to a name in an outer scope.
///
/// ## Example
/// ```python
/// class Foo:
/// def get_bar(self):
/// nonlocal bar
/// ...
/// ```
///
/// Use instead:
/// ```python
/// class Foo:
/// bar = 1
///
/// def get_bar(self):
/// nonlocal bar
/// ...
/// ```
///
/// ## References
/// - [Python documentation](https://docs.python.org/3/reference/simple_stmts.html#nonlocal)
/// - [PEP 3104](https://peps.python.org/pep-3104/)
#[violation]
pub struct NonlocalWithoutBinding {
pub(crate) name: String,

View file

@ -74,6 +74,43 @@ impl ExpectedParams {
}
}
/// ## What it does
/// Checks for "special" methods that have an unexpected method signature.
///
/// ## Why is this bad?
/// "Special" methods, like `__len__`, are expected to adhere to a specific,
/// standard function signature. Implementing a "special" method using a
/// non-standard function signature can lead to unexpected and surprising
/// behavior for users of a given class.
///
/// ## Example
/// ```python
/// class Bookshelf:
/// def __init__(self):
/// self._books = ["Foo", "Bar", "Baz"]
///
/// def __len__(self, index): # __len__ does not except an index parameter
/// return len(self._books)
///
/// def __getitem__(self, index):
/// return self._books[index]
/// ```
///
/// Use instead:
/// ```python
/// class Bookshelf:
/// def __init__(self):
/// self._books = ["Foo", "Bar", "Baz"]
///
/// def __len__(self):
/// return len(self._books)
///
/// def __getitem__(self, index):
/// return self._books[index]
/// ```
///
/// ## References
/// - [Python documentation](https://docs.python.org/3/reference/datamodel.html)
#[violation]
pub struct UnexpectedSpecialMethodSignature {
method_name: String,