Skip to content

Commit ac150b9

Browse files
authored
Spruce up docs for flake8-pyi rules (part 2) (#10494)
- Improve clarity over the motivation for some rules - Improve links to external references. In particular, reduce links to PEPs, as PEPs are generally historical documents rather than pieces of living documentation. Where possible, it's better to link to the official typing spec, the other docs at typing.readthedocs.io/en/latest, or the docs at docs.python.org/3/library/typing.html. - Use more concise language in a few places
1 parent d9ac170 commit ac150b9

9 files changed

+69
-38
lines changed

crates/ruff_linter/src/rules/flake8_pyi/rules/simple_defaults.rs

+12-14
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,30 @@ use crate::rules::flake8_pyi::rules::TypingModule;
1717
use crate::settings::types::PythonVersion;
1818

1919
/// ## What it does
20-
/// Checks for typed function arguments in stubs with default values that
21-
/// are not "simple" /// (i.e., `int`, `float`, `complex`, `bytes`, `str`,
22-
/// `bool`, `None`, `...`, or simple container literals).
20+
/// Checks for typed function arguments in stubs with complex default values.
2321
///
2422
/// ## Why is this bad?
25-
/// Stub (`.pyi`) files exist to define type hints, and are not evaluated at
26-
/// runtime. As such, function arguments in stub files should not have default
27-
/// values, as they are ignored by type checkers.
28-
///
29-
/// However, the use of default values may be useful for IDEs and other
30-
/// consumers of stub files, and so "simple" values may be worth including and
31-
/// are permitted by this rule.
23+
/// Stub (`.pyi`) files exist as "data files" for static analysis tools, and
24+
/// are not evaluated at runtime. While simple default values may be useful for
25+
/// some tools that consume stubs, such as IDEs, they are ignored by type
26+
/// checkers.
3227
///
3328
/// Instead of including and reproducing a complex value, use `...` to indicate
34-
/// that the assignment has a default value, but that the value is non-simple
35-
/// or varies according to the current platform or Python version.
29+
/// that the assignment has a default value, but that the value is "complex" or
30+
/// varies according to the current platform or Python version. For the
31+
/// purposes of this rule, any default value counts as "complex" unless it is
32+
/// a literal `int`, `float`, `complex`, `bytes`, `str`, `bool`, `None`, `...`,
33+
/// or a simple container literal.
3634
///
3735
/// ## Example
3836
/// ```python
39-
/// def foo(arg: List[int] = []) -> None:
37+
/// def foo(arg: list[int] = list(range(10_000))) -> None:
4038
/// ...
4139
/// ```
4240
///
4341
/// Use instead:
4442
/// ```python
45-
/// def foo(arg: List[int] = ...) -> None:
43+
/// def foo(arg: list[int] = ...) -> None:
4644
/// ...
4745
/// ```
4846
///

crates/ruff_linter/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ use crate::checkers::ast::Checker;
1212
/// in stub (`.pyi`) files.
1313
///
1414
/// ## Why is this bad?
15-
/// If a function has a default value where the string or bytes representation
16-
/// is greater than 50 characters, it is likely to be an implementation detail
17-
/// or a constant that varies depending on the system you're running on.
15+
/// If a function or variable has a default value where the string or bytes
16+
/// representation is greater than 50 characters long, it is likely to be an
17+
/// implementation detail or a constant that varies depending on the system
18+
/// you're running on.
1819
///
19-
/// Consider replacing such constants with ellipses (`...`).
20+
/// Although IDEs may find them useful, default values are ignored by type
21+
/// checkers, the primary consumers of stub files. Replace very long constants
22+
/// with ellipses (`...`) to simplify the stub.
2023
///
2124
/// ## Example
2225
/// ```python

crates/ruff_linter/src/rules/flake8_pyi/rules/type_alias_naming.rs

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ impl Violation for SnakeCaseTypeAlias {
5757
///
5858
/// _MyType: TypeAlias = int
5959
/// ```
60+
///
61+
/// ## References
62+
/// - [PEP 484: Type Aliases](https://peps.python.org/pep-0484/#type-aliases)
6063
#[violation]
6164
pub struct TSuffixedTypeAlias {
6265
name: String,

crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,25 @@ use crate::checkers::ast::Checker;
1111
/// Checks for the presence of multiple literal types in a union.
1212
///
1313
/// ## Why is this bad?
14-
/// Literal types accept multiple arguments, and it is clearer to specify them
15-
/// as a single literal.
14+
/// `Literal["foo", 42]` has identical semantics to
15+
/// `Literal["foo"] | Literal[42]`, but is clearer and more concise.
1616
///
1717
/// ## Example
1818
/// ```python
1919
/// from typing import Literal
2020
///
21-
/// field: Literal[1] | Literal[2]
21+
/// field: Literal[1] | Literal[2] | str
2222
/// ```
2323
///
2424
/// Use instead:
2525
/// ```python
2626
/// from typing import Literal
2727
///
28-
/// field: Literal[1, 2]
28+
/// field: Literal[1, 2] | str
2929
/// ```
30+
///
31+
/// ## References
32+
/// - [Python documentation: `typing.Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)
3033
#[violation]
3134
pub struct UnnecessaryLiteralUnion {
3235
members: Vec<String>,

crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_type_union.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ use crate::checkers::ast::Checker;
1212
/// Checks for the presence of multiple `type`s in a union.
1313
///
1414
/// ## Why is this bad?
15-
/// The `type` built-in function accepts unions, and it is clearer to
16-
/// explicitly specify them as a single `type`.
15+
/// `type[T | S]` has identical semantics to `type[T] | type[S]` in a type
16+
/// annotation, but is cleaner and more concise.
1717
///
1818
/// ## Example
1919
/// ```python
20-
/// field: type[int] | type[float]
20+
/// field: type[int] | type[float] | str
2121
/// ```
2222
///
2323
/// Use instead:
2424
/// ```python
25-
/// field: type[int | float]
25+
/// field: type[int | float] | str
2626
/// ```
2727
#[violation]
2828
pub struct UnnecessaryTypeUnion {

crates/ruff_linter/src/rules/flake8_pyi/rules/unrecognized_platform.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ use crate::registry::Rule;
1515
///
1616
/// ## Why is this bad?
1717
/// Some `sys.platform` checks are too complex for type checkers to
18-
/// understand, and thus result in false positives. `sys.platform` checks
19-
/// should be simple string comparisons, like `sys.platform == "linux"`.
18+
/// understand, and thus result in incorrect inferences by these tools.
19+
/// `sys.platform` checks should be simple string comparisons, like
20+
/// `if sys.platform == "linux"`.
2021
///
2122
/// ## Example
2223
/// ```python
@@ -39,7 +40,7 @@ use crate::registry::Rule;
3940
/// ```
4041
///
4142
/// ## References
42-
/// - [PEP 484](https://peps.python.org/pep-0484/#version-and-platform-checking)
43+
/// - [Typing stubs documentation: Version and Platform Checks](https://typing.readthedocs.io/en/latest/source/stubs.html#version-and-platform-checks)
4344
#[violation]
4445
pub struct UnrecognizedPlatformCheck;
4546

@@ -75,7 +76,7 @@ impl Violation for UnrecognizedPlatformCheck {
7576
/// ```
7677
///
7778
/// ## References
78-
/// - [PEP 484](https://peps.python.org/pep-0484/#version-and-platform-checking)
79+
/// - [Typing stubs documentation: Version and Platform Checks](https://typing.readthedocs.io/en/latest/source/stubs.html#version-and-platform-checks)
7980
#[violation]
8081
pub struct UnrecognizedPlatformName {
8182
platform: String,

crates/ruff_linter/src/rules/flake8_pyi/rules/unrecognized_version_info.rs

+9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ use crate::registry::Rule;
3131
/// if sys.version_info[0] == 2:
3232
/// ...
3333
/// ```
34+
///
35+
/// ## References
36+
/// - [Typing stubs documentation: Version and Platform Checks](https://typing.readthedocs.io/en/latest/source/stubs.html#version-and-platform-checks)
3437
#[violation]
3538
pub struct UnrecognizedVersionInfoCheck;
3639

@@ -69,6 +72,9 @@ impl Violation for UnrecognizedVersionInfoCheck {
6972
/// if sys.version_info >= (3, 4):
7073
/// ...
7174
/// ```
75+
///
76+
/// ## References
77+
/// - [Typing stubs documentation: Version and Platform Checks](https://typing.readthedocs.io/en/latest/source/stubs.html#version-and-platform-checks)
7278
#[violation]
7379
pub struct PatchVersionComparison;
7480

@@ -104,6 +110,9 @@ impl Violation for PatchVersionComparison {
104110
/// if sys.version_info[0] == 3:
105111
/// ...
106112
/// ```
113+
///
114+
/// ## References
115+
/// - [Typing stubs documentation: Version and Platform Checks](https://typing.readthedocs.io/en/latest/source/stubs.html#version-and-platform-checks)
107116
#[violation]
108117
pub struct WrongTupleLengthVersionComparison {
109118
expected_length: usize,

crates/ruff_linter/src/rules/flake8_pyi/rules/unsupported_method_call_on_all.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,28 @@ use crate::checkers::ast::Checker;
1717
///
1818
/// ## Example
1919
/// ```python
20-
/// __all__ = ["A"]
21-
/// __all__.append("B")
20+
/// import sys
21+
///
22+
/// __all__ = ["A", "B"]
23+
///
24+
/// if sys.version_info >= (3, 10):
25+
/// __all__.append("C")
26+
///
27+
/// if sys.version_info >= (3, 11):
28+
/// __all__.remove("B")
2229
/// ```
2330
///
2431
/// Use instead:
2532
/// ```python
33+
/// import sys
34+
///
2635
/// __all__ = ["A"]
27-
/// __all__ += ["B"]
36+
///
37+
/// if sys.version_info < (3, 11):
38+
/// __all__ += ["B"]
39+
///
40+
/// if sys.version_info >= (3, 10):
41+
/// __all__ += ["C"]
2842
/// ```
2943
#[violation]
3044
pub struct UnsupportedMethodCallOnAll {

crates/ruff_linter/src/rules/flake8_pyi/rules/unused_private_type_definition.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Violation for UnusedPrivateTypeVar {
4545
///
4646
/// ## Why is this bad?
4747
/// A private `typing.Protocol` that is defined but not used is likely a
48-
/// mistake, and should either be used, made public, or removed to avoid
48+
/// mistake. It should either be used, made public, or removed to avoid
4949
/// confusion.
5050
///
5151
/// ## Example
@@ -83,11 +83,11 @@ impl Violation for UnusedPrivateProtocol {
8383
}
8484

8585
/// ## What it does
86-
/// Checks for the presence of unused private `typing.TypeAlias` definitions.
86+
/// Checks for the presence of unused private type aliases.
8787
///
8888
/// ## Why is this bad?
89-
/// A private `typing.TypeAlias` that is defined but not used is likely a
90-
/// mistake, and should either be used, made public, or removed to avoid
89+
/// A private type alias that is defined but not used is likely a
90+
/// mistake. It should either be used, made public, or removed to avoid
9191
/// confusion.
9292
///
9393
/// ## Example
@@ -125,7 +125,7 @@ impl Violation for UnusedPrivateTypeAlias {
125125
///
126126
/// ## Why is this bad?
127127
/// A private `typing.TypedDict` that is defined but not used is likely a
128-
/// mistake, and should either be used, made public, or removed to avoid
128+
/// mistake. It should either be used, made public, or removed to avoid
129129
/// confusion.
130130
///
131131
/// ## Example

0 commit comments

Comments
 (0)