Add documentation for remaining undocumented lint rules (#7750)
This commit is contained in:
@@ -6,8 +6,6 @@ use std::fmt::Formatter;
|
||||
|
||||
use strum_macros::{AsRefStr, EnumIter};
|
||||
|
||||
use ruff_diagnostics::Violation;
|
||||
|
||||
use crate::registry::{AsRule, Linter};
|
||||
use crate::rule_selector::is_single_rule_selector;
|
||||
use crate::rules;
|
||||
|
||||
@@ -412,7 +412,7 @@ impl Violation for MissingReturnTypeClassMethod {
|
||||
/// ## References
|
||||
/// - [PEP 484](https://www.python.org/dev/peps/pep-0484/#the-any-type)
|
||||
/// - [Python documentation: `typing.Any`](https://docs.python.org/3/library/typing.html#typing.Any)
|
||||
/// - [Mypy: The Any type](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#the-any-type)
|
||||
/// - [Mypy documentation: The Any type](https://mypy.readthedocs.io/en/stable/kinds_of_types.html#the-any-type)
|
||||
#[violation]
|
||||
pub struct AnyType {
|
||||
name: String,
|
||||
|
||||
@@ -88,6 +88,32 @@ impl Violation for SubprocessWithoutShellEqualsTrue {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for method calls that set the `shell` parameter to `true` when
|
||||
/// invoking a subprocess.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Setting the `shell` parameter to `true` when invoking a subprocess can
|
||||
/// introduce security vulnerabilities, as it allows shell metacharacters and
|
||||
/// whitespace to be passed to child processes, potentially leading to shell
|
||||
/// injection attacks. It is recommended to avoid using `shell=True` unless
|
||||
/// absolutely necessary, and when used, to ensure that all inputs are properly
|
||||
/// sanitized and quoted to prevent such vulnerabilities.
|
||||
///
|
||||
/// ## Known problems
|
||||
/// Prone to false positives as it is triggered on any function call with a
|
||||
/// `shell=True` parameter.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// import subprocess
|
||||
///
|
||||
/// user_input = input("Enter a command: ")
|
||||
/// subprocess.run(user_input, shell=True)
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Security Considerations](https://docs.python.org/3/library/subprocess.html#security-considerations)
|
||||
#[violation]
|
||||
pub struct CallWithShellEqualsTrue;
|
||||
|
||||
@@ -98,6 +124,42 @@ impl Violation for CallWithShellEqualsTrue {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for calls that start a process with a shell, providing guidance on
|
||||
/// whether the usage is safe or not.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Starting a process with a shell can introduce security risks, such as
|
||||
/// code injection vulnerabilities. It's important to be aware of whether the
|
||||
/// usage of the shell is safe or not.
|
||||
///
|
||||
/// This rule triggers on functions like `os.system`, `popen`, etc., which
|
||||
/// start processes with a shell. It evaluates whether the provided command
|
||||
/// is a literal string or an expression. If the command is a literal string,
|
||||
/// it's considered safe. If the command is an expression, it's considered
|
||||
/// (potentially) unsafe.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// # Safe usage (literal string)
|
||||
/// command = "ls -l"
|
||||
/// os.system(command)
|
||||
///
|
||||
/// # Potentially unsafe usage (expression)
|
||||
/// cmd = get_user_input()
|
||||
/// os.system(cmd)
|
||||
/// ```
|
||||
///
|
||||
/// ## Note
|
||||
/// The `subprocess` module provides more powerful facilities for spawning new
|
||||
/// processes and retrieving their results, and using that module is preferable
|
||||
/// to using `os.system` or similar functions. Consider replacing such usages
|
||||
/// with `subprocess.call` or related functions.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `subprocess`](https://docs.python.org/3/library/subprocess.html)
|
||||
#[violation]
|
||||
pub struct StartProcessWithAShell {
|
||||
seems_safe: bool,
|
||||
@@ -114,6 +176,26 @@ impl Violation for StartProcessWithAShell {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for functions that start a process without a shell.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// The `subprocess` module provides more powerful facilities for spawning new
|
||||
/// processes and retrieving their results; using that module is preferable to
|
||||
/// using these functions.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// subprocess.Popen(["/bin/mycmd", "myarg"])
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Replacing the `os.spawn` family](https://docs.python.org/3/library/subprocess.html#replacing-the-os-spawn-family)
|
||||
#[violation]
|
||||
pub struct StartProcessWithNoShell;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ use crate::registry::AsRule;
|
||||
/// ```
|
||||
/// ## References
|
||||
/// - [Python documentation: The `Any` type](https://docs.python.org/3/library/typing.html#the-any-type)
|
||||
/// - [Mypy documentation](https://mypy.readthedocs.io/en/latest/dynamic_typing.html#any-vs-object)
|
||||
/// - [Mypy documentation: Any vs. object](https://mypy.readthedocs.io/en/latest/dynamic_typing.html#any-vs-object)
|
||||
#[violation]
|
||||
pub struct AnyEqNeAnnotation {
|
||||
method_name: String,
|
||||
|
||||
@@ -6,6 +6,25 @@ use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for the presence of docstrings in stub files.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub files should omit docstrings, as they're intended to provide type
|
||||
/// hints, rather than documentation.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def func(param: int) -> str:
|
||||
/// """This is a docstring."""
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def func(param: int) -> str:
|
||||
/// ...
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct DocstringInStub;
|
||||
|
||||
|
||||
@@ -5,6 +5,17 @@ use ruff_macros::{derive_message_formats, violation};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for the presence of the `from __future__ import annotations` import
|
||||
/// statement in stub files.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub files are already evaluated under `annotations` semantics. As such,
|
||||
/// the `from __future__ import annotations` import statement has no effect
|
||||
/// and should be omitted.
|
||||
///
|
||||
/// ## Resources
|
||||
/// - [Static Typing with Python: Type Stubs](https://typing.readthedocs.io/en/latest/source/stubs.html)
|
||||
#[violation]
|
||||
pub struct FutureAnnotationsInStub;
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@ 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.
|
||||
@@ -23,13 +20,18 @@ pub struct NumericLiteralTooLong;
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def foo(arg: int = 12345678901) -> None: ...
|
||||
/// def foo(arg: int = 12345678901) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def foo(arg: int = ...) -> None: ...
|
||||
/// def foo(arg: int = ...) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct NumericLiteralTooLong;
|
||||
|
||||
impl AlwaysFixableViolation for NumericLiteralTooLong {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
|
||||
@@ -7,6 +7,32 @@ use crate::checkers::ast::Checker;
|
||||
use crate::fix;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for the presence of the `pass` statement within a class body
|
||||
/// in a stub (`.pyi`) file.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// In stub files, class definitions are intended to provide type hints, but
|
||||
/// are never actually evaluated. As such, it's unnecessary to include a `pass`
|
||||
/// statement in a class body, since it has no effect.
|
||||
///
|
||||
/// Instead of `pass`, prefer `...` to indicate that the class body is empty
|
||||
/// and adhere to common stub file conventions.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// class MyClass:
|
||||
/// pass
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// class MyClass:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Mypy documentation: Stub files](https://mypy.readthedocs.io/en/stable/stubs.html)
|
||||
#[violation]
|
||||
pub struct PassInClassBody;
|
||||
|
||||
|
||||
@@ -6,6 +6,26 @@ use ruff_macros::{derive_message_formats, violation};
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for quoted type annotations in stub (`.pyi`) files, which should be avoided.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub files are evaluated using `annotations` semantics, as if
|
||||
/// `from __future__ import annotations` were included in the file. As such,
|
||||
/// quotes are never required for type annotations in stub files, and should be
|
||||
/// omitted.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def function() -> "int":
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def function() -> int:
|
||||
/// ...
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct QuotedAnnotationInStub;
|
||||
|
||||
|
||||
@@ -15,6 +15,38 @@ use crate::registry::AsRule;
|
||||
use crate::rules::flake8_pyi::rules::TypingModule;
|
||||
use crate::settings::types::PythonVersion;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for typed function arguments in stubs with default values that
|
||||
/// are not "simple" /// (i.e., `int`, `float`, `complex`, `bytes`, `str`,
|
||||
/// `bool`, `None`, `...`, or simple container literals).
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub (`.pyi`) files exist to define type hints, and are not evaluated at
|
||||
/// runtime. As such, function arguments in stub files should not have default
|
||||
/// values, as they are ignored by type checkers.
|
||||
///
|
||||
/// However, the use of default values may be useful for IDEs and other
|
||||
/// consumers of stub files, and so "simple" values may be worth including and
|
||||
/// are permitted by this rule.
|
||||
///
|
||||
/// Instead of including and reproducing a complex value, use `...` to indicate
|
||||
/// that the assignment has a default value, but that the value is non-simple
|
||||
/// or varies according to the current platform or Python version.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def foo(arg: List[int] = []) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def foo(arg: List[int] = ...) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [`flake8-pyi`](https://github.com/PyCQA/flake8-pyi/blob/main/ERRORCODES.md)
|
||||
#[violation]
|
||||
pub struct TypedArgumentDefaultInStub;
|
||||
|
||||
@@ -29,6 +61,38 @@ impl AlwaysFixableViolation for TypedArgumentDefaultInStub {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for untyped function arguments in stubs with default values that
|
||||
/// are not "simple" /// (i.e., `int`, `float`, `complex`, `bytes`, `str`,
|
||||
/// `bool`, `None`, `...`, or simple container literals).
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub (`.pyi`) files exist to define type hints, and are not evaluated at
|
||||
/// runtime. As such, function arguments in stub files should not have default
|
||||
/// values, as they are ignored by type checkers.
|
||||
///
|
||||
/// However, the use of default values may be useful for IDEs and other
|
||||
/// consumers of stub files, and so "simple" values may be worth including and
|
||||
/// are permitted by this rule.
|
||||
///
|
||||
/// Instead of including and reproducing a complex value, use `...` to indicate
|
||||
/// that the assignment has a default value, but that the value is non-simple
|
||||
/// or varies according to the current platform or Python version.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def foo(arg=[]) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def foo(arg=...) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [`flake8-pyi`](https://github.com/PyCQA/flake8-pyi/blob/main/ERRORCODES.md)
|
||||
#[violation]
|
||||
pub struct ArgumentDefaultInStub;
|
||||
|
||||
@@ -43,6 +107,36 @@ impl AlwaysFixableViolation for ArgumentDefaultInStub {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for assignments in stubs with default values that are not "simple"
|
||||
/// (i.e., `int`, `float`, `complex`, `bytes`, `str`, `bool`, `None`, `...`, or
|
||||
/// simple container literals).
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub (`.pyi`) files exist to define type hints, and are not evaluated at
|
||||
/// runtime. As such, assignments in stub files should not include values,
|
||||
/// as they are ignored by type checkers.
|
||||
///
|
||||
/// However, the use of such values may be useful for IDEs and other consumers
|
||||
/// of stub files, and so "simple" values may be worth including and are
|
||||
/// permitted by this rule.
|
||||
///
|
||||
/// Instead of including and reproducing a complex value, use `...` to indicate
|
||||
/// that the assignment has a default value, but that the value is non-simple
|
||||
/// or varies according to the current platform or Python version.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// foo: str = "..."
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// foo: str = ...
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [`flake8-pyi`](https://github.com/PyCQA/flake8-pyi/blob/main/ERRORCODES.md)
|
||||
#[violation]
|
||||
pub struct AssignmentDefaultInStub;
|
||||
|
||||
@@ -57,6 +151,12 @@ impl AlwaysFixableViolation for AssignmentDefaultInStub {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does?
|
||||
/// Checks for unannotated assignments in stub (`.pyi`) files.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub files exist to provide type hints, and are never executed. As such,
|
||||
/// all assignments in stub files should be annotated with a type.
|
||||
#[violation]
|
||||
pub struct UnannotatedAssignmentInStub {
|
||||
name: String,
|
||||
@@ -70,11 +170,6 @@ impl Violation for UnannotatedAssignmentInStub {
|
||||
}
|
||||
}
|
||||
|
||||
#[violation]
|
||||
pub struct UnassignedSpecialVariableInStub {
|
||||
name: String,
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks that `__all__`, `__match_args__`, and `__slots__` variables are
|
||||
/// assigned to values when defined in stub files.
|
||||
@@ -93,6 +188,11 @@ pub struct UnassignedSpecialVariableInStub {
|
||||
/// ```python
|
||||
/// __all__: list[str] = ["foo", "bar"]
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct UnassignedSpecialVariableInStub {
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Violation for UnassignedSpecialVariableInStub {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
|
||||
@@ -8,11 +8,9 @@ use ruff_text_size::Ranged;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
#[violation]
|
||||
pub struct StringOrBytesTooLong;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for the use of string and bytes literals longer than 50 characters.
|
||||
/// Checks for the use of string and bytes literals longer than 50 characters
|
||||
/// in stub (`.pyi`) files.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// If a function has a default value where the string or bytes representation
|
||||
@@ -23,13 +21,18 @@ pub struct StringOrBytesTooLong;
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def foo(arg: str = "51 character stringgggggggggggggggggggggggggggggggg") -> None: ...
|
||||
/// def foo(arg: str = "51 character stringgggggggggggggggggggggggggggggggg") -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def foo(arg: str = ...) -> None: ...
|
||||
/// def foo(arg: str = ...) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct StringOrBytesTooLong;
|
||||
|
||||
impl AlwaysFixableViolation for StringOrBytesTooLong {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
|
||||
@@ -5,6 +5,28 @@ use ruff_python_ast::Stmt;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for functions in stub (`.pyi`) files that contain multiple
|
||||
/// statements.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Stub files are never executed, and are only intended to define type hints.
|
||||
/// As such, functions in stub files should not contain functional code, and
|
||||
/// should instead contain only a single statement (e.g., `...`).
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// def function():
|
||||
/// x = 1
|
||||
/// y = 2
|
||||
/// return x + y
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// def function():
|
||||
/// ...
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct StubBodyMultipleStatements;
|
||||
|
||||
|
||||
@@ -5,6 +5,22 @@ use ruff_macros::{derive_message_formats, violation};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for type aliases that do not use the CamelCase naming convention.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// It's conventional to use the CamelCase naming convention for type aliases,
|
||||
/// to distinguish them from other variables.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// type_alias_name: TypeAlias = int
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// TypeAliasName: TypeAlias = int
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct SnakeCaseTypeAlias {
|
||||
name: String,
|
||||
@@ -18,6 +34,25 @@ impl Violation for SnakeCaseTypeAlias {
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for private type alias definitions suffixed with 'T'.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// It's conventional to use the 'T' suffix for type variables; the use of
|
||||
/// such a suffix implies that the object is a `TypeVar`.
|
||||
///
|
||||
/// Adding the 'T' suffix to a non-`TypeVar`, it can be misleading and should
|
||||
/// be avoided.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// MyTypeT = int
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// MyType = int
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct TSuffixedTypeAlias {
|
||||
name: String,
|
||||
|
||||
@@ -31,7 +31,7 @@ use ruff_text_size::TextSize;
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [mypy](https://mypy.readthedocs.io/en/stable/common_issues.html#spurious-errors-and-locally-silencing-the-checker)
|
||||
/// - [<ypy](https://mypy.readthedocs.io/en/stable/common_issues.html#spurious-errors-and-locally-silencing-the-checker)
|
||||
#[violation]
|
||||
pub struct BlanketTypeIgnore;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user