mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
Add documentation for mccabe, isort, and flake8-annotations (#2691)
This commit is contained in:
parent
8a98cfc4b8
commit
7d5fb0de8a
21 changed files with 713 additions and 23 deletions
28
README.md
28
README.md
|
@ -748,7 +748,7 @@ For more, see [mccabe](https://pypi.org/project/mccabe/) on PyPI.
|
||||||
|
|
||||||
| Code | Name | Message | Fix |
|
| Code | Name | Message | Fix |
|
||||||
| ---- | ---- | ------- | --- |
|
| ---- | ---- | ------- | --- |
|
||||||
| C901 | function-is-too-complex | `{name}` is too complex ({complexity}) | |
|
| C901 | [function-is-too-complex](https://github.com/charliermarsh/ruff/blob/main/docs/rules/function-is-too-complex.md) | `{name}` is too complex ({complexity}) | |
|
||||||
|
|
||||||
### isort (I)
|
### isort (I)
|
||||||
|
|
||||||
|
@ -756,8 +756,8 @@ For more, see [isort](https://pypi.org/project/isort/) on PyPI.
|
||||||
|
|
||||||
| Code | Name | Message | Fix |
|
| Code | Name | Message | Fix |
|
||||||
| ---- | ---- | ------- | --- |
|
| ---- | ---- | ------- | --- |
|
||||||
| I001 | unsorted-imports | Import block is un-sorted or un-formatted | 🛠 |
|
| I001 | [unsorted-imports](https://github.com/charliermarsh/ruff/blob/main/docs/rules/unsorted-imports.md) | Import block is un-sorted or un-formatted | 🛠 |
|
||||||
| I002 | missing-required-import | Missing required import: `{name}` | 🛠 |
|
| I002 | [missing-required-import](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-required-import.md) | Missing required import: `{name}` | 🛠 |
|
||||||
|
|
||||||
### pep8-naming (N)
|
### pep8-naming (N)
|
||||||
|
|
||||||
|
@ -899,17 +899,17 @@ For more, see [flake8-annotations](https://pypi.org/project/flake8-annotations/)
|
||||||
|
|
||||||
| Code | Name | Message | Fix |
|
| Code | Name | Message | Fix |
|
||||||
| ---- | ---- | ------- | --- |
|
| ---- | ---- | ------- | --- |
|
||||||
| ANN001 | missing-type-function-argument | Missing type annotation for function argument `{name}` | |
|
| ANN001 | [missing-type-function-argument](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-type-function-argument.md) | Missing type annotation for function argument `{name}` | |
|
||||||
| ANN002 | missing-type-args | Missing type annotation for `*{name}` | |
|
| ANN002 | [missing-type-args](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-type-args.md) | Missing type annotation for `*{name}` | |
|
||||||
| ANN003 | missing-type-kwargs | Missing type annotation for `**{name}` | |
|
| ANN003 | [missing-type-kwargs](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-type-kwargs.md) | Missing type annotation for `**{name}` | |
|
||||||
| ANN101 | missing-type-self | Missing type annotation for `{name}` in method | |
|
| ANN101 | [missing-type-self](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-type-self.md) | Missing type annotation for `{name}` in method | |
|
||||||
| ANN102 | missing-type-cls | Missing type annotation for `{name}` in classmethod | |
|
| ANN102 | [missing-type-cls](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-type-cls.md) | Missing type annotation for `{name}` in classmethod | |
|
||||||
| ANN201 | missing-return-type-public-function | Missing return type annotation for public function `{name}` | |
|
| ANN201 | [missing-return-type-public-function](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-return-type-public-function.md) | Missing return type annotation for public function `{name}` | |
|
||||||
| ANN202 | missing-return-type-private-function | Missing return type annotation for private function `{name}` | |
|
| ANN202 | [missing-return-type-private-function](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-return-type-private-function.md) | Missing return type annotation for private function `{name}` | |
|
||||||
| ANN204 | missing-return-type-special-method | Missing return type annotation for special method `{name}` | 🛠 |
|
| ANN204 | [missing-return-type-special-method](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-return-type-special-method.md) | Missing return type annotation for special method `{name}` | 🛠 |
|
||||||
| ANN205 | missing-return-type-static-method | Missing return type annotation for staticmethod `{name}` | |
|
| ANN205 | [missing-return-type-static-method](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-return-type-static-method.md) | Missing return type annotation for staticmethod `{name}` | |
|
||||||
| ANN206 | missing-return-type-class-method | Missing return type annotation for classmethod `{name}` | |
|
| ANN206 | [missing-return-type-class-method](https://github.com/charliermarsh/ruff/blob/main/docs/rules/missing-return-type-class-method.md) | Missing return type annotation for classmethod `{name}` | |
|
||||||
| ANN401 | dynamically-typed-expression | Dynamically typed expressions (typing.Any) are disallowed in `{name}` | |
|
| ANN401 | [dynamically-typed-expression](https://github.com/charliermarsh/ruff/blob/main/docs/rules/dynamically-typed-expression.md) | Dynamically typed expressions (typing.Any) are disallowed in `{name}` | |
|
||||||
|
|
||||||
### flake8-bandit (S)
|
### flake8-bandit (S)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,25 @@ use crate::visibility;
|
||||||
use crate::visibility::Visibility;
|
use crate::visibility::Visibility;
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that function arguments have type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any provided arguments match expectation.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// def foo(x):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// def foo(x: int):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
pub struct MissingTypeFunctionArgument {
|
pub struct MissingTypeFunctionArgument {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -29,6 +48,25 @@ impl Violation for MissingTypeFunctionArgument {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that function `*args` arguments have type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any provided arguments match expectation.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// def foo(*args):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// def foo(*args: int):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
pub struct MissingTypeArgs {
|
pub struct MissingTypeArgs {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -42,6 +80,25 @@ impl Violation for MissingTypeArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that function `**kwargs` arguments have type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any provided arguments match expectation.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// def foo(**kwargs):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// def foo(**kwargs: int):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
pub struct MissingTypeKwargs {
|
pub struct MissingTypeKwargs {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -55,6 +112,30 @@ impl Violation for MissingTypeKwargs {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that instance method `self` arguments have type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any provided arguments match expectation.
|
||||||
|
///
|
||||||
|
/// Note that many type checkers will infer the type of `self` automatically, so this
|
||||||
|
/// annotation is not strictly necessary.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// def bar(self):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// def bar(self: "Foo"):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
pub struct MissingTypeSelf {
|
pub struct MissingTypeSelf {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -68,6 +149,32 @@ impl Violation for MissingTypeSelf {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that class method `cls` arguments have type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any provided arguments match expectation.
|
||||||
|
///
|
||||||
|
/// Note that many type checkers will infer the type of `cls` automatically, so this
|
||||||
|
/// annotation is not strictly necessary.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// @classmethod
|
||||||
|
/// def bar(cls):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// @classmethod
|
||||||
|
/// def bar(cls: Type["Foo"]):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
pub struct MissingTypeCls {
|
pub struct MissingTypeCls {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -81,6 +188,25 @@ impl Violation for MissingTypeCls {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that public functions and methods have return type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the return types of functions. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any returned values, and the types expected by callers, match expectation.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// def add(a, b):
|
||||||
|
/// return a + b
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// def add(a: int, b: int) -> int:
|
||||||
|
/// return a + b
|
||||||
|
/// ```
|
||||||
pub struct MissingReturnTypePublicFunction {
|
pub struct MissingReturnTypePublicFunction {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -94,6 +220,25 @@ impl Violation for MissingReturnTypePublicFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that private functions and methods have return type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the return types of functions. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any returned values, and the types expected by callers, match expectation.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// def _add(a, b):
|
||||||
|
/// return a + b
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// def _add(a: int, b: int) -> int:
|
||||||
|
/// return a + b
|
||||||
|
/// ```
|
||||||
pub struct MissingReturnTypePrivateFunction {
|
pub struct MissingReturnTypePrivateFunction {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -107,6 +252,38 @@ impl Violation for MissingReturnTypePrivateFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that "special" methods, like `__init__`, `__new__`, and `__call__`, have
|
||||||
|
/// return type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the return types of functions. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any returned values, and the types expected by callers, match expectation.
|
||||||
|
///
|
||||||
|
/// Note that type checkers often allow you to omit the return type annotation for
|
||||||
|
/// `__init__` methods, as long as at least one argument has a type annotation. To
|
||||||
|
/// opt-in to this behavior, use the `mypy-init-return` setting in your `pyproject.toml`
|
||||||
|
/// or `ruff.toml` file:
|
||||||
|
///
|
||||||
|
/// ```toml
|
||||||
|
/// [tool.ruff.flake8-annotations]
|
||||||
|
/// mypy-init-return = true
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// def __init__(self, x: int):
|
||||||
|
/// self.x = x
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// def __init__(self, x: int) -> None:
|
||||||
|
/// self.x = x
|
||||||
|
/// ```
|
||||||
pub struct MissingReturnTypeSpecialMethod {
|
pub struct MissingReturnTypeSpecialMethod {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -124,6 +301,29 @@ impl AlwaysAutofixableViolation for MissingReturnTypeSpecialMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that static methods have return type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the return types of functions. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any returned values, and the types expected by callers, match expectation.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// @staticmethod
|
||||||
|
/// def bar():
|
||||||
|
/// return 1
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// @staticmethod
|
||||||
|
/// def bar() -> int:
|
||||||
|
/// return 1
|
||||||
|
/// ```
|
||||||
pub struct MissingReturnTypeStaticMethod {
|
pub struct MissingReturnTypeStaticMethod {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -137,6 +337,29 @@ impl Violation for MissingReturnTypeStaticMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that class methods have return type annotations.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Type annotations are a good way to document the return types of functions. They also
|
||||||
|
/// help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
/// any returned values, and the types expected by callers, match expectation.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// @classmethod
|
||||||
|
/// def bar(cls):
|
||||||
|
/// return 1
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// class Foo:
|
||||||
|
/// @classmethod
|
||||||
|
/// def bar(cls) -> int:
|
||||||
|
/// return 1
|
||||||
|
/// ```
|
||||||
pub struct MissingReturnTypeClassMethod {
|
pub struct MissingReturnTypeClassMethod {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
@ -150,6 +373,25 @@ impl Violation for MissingReturnTypeClassMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks that an expression is annotated with a more specific type than `Any`.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// `Any` is a type that can be anything, and it is the default type for
|
||||||
|
/// unannotated expressions. It is better to be explicit about the type of an
|
||||||
|
/// expression, and to use `Any` only when it is really needed.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// def foo(x: Any):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// def foo(x: int):
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
pub struct DynamicallyTypedExpression {
|
pub struct DynamicallyTypedExpression {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,26 @@ use crate::source_code::{Locator, Stylist};
|
||||||
use crate::violation::AlwaysAutofixableViolation;
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Adds any required imports, as specified by the user, to the top of the file.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// In some projects, certain imports are required to be present in all files. For
|
||||||
|
/// example, some projects assume that `from __future__ import annotations` is enabled,
|
||||||
|
/// and thus require that import to be present in all files. Omitting a "required" import
|
||||||
|
/// (as specified by the user) can cause errors or unexpected behavior.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// import typing
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// from __future__ import annotations
|
||||||
|
///
|
||||||
|
/// import typing
|
||||||
|
/// ```
|
||||||
pub struct MissingRequiredImport(pub String);
|
pub struct MissingRequiredImport(pub String);
|
||||||
);
|
);
|
||||||
impl AlwaysAutofixableViolation for MissingRequiredImport {
|
impl AlwaysAutofixableViolation for MissingRequiredImport {
|
||||||
|
|
|
@ -19,6 +19,24 @@ use crate::source_code::{Indexer, Locator, Stylist};
|
||||||
use crate::violation::AlwaysAutofixableViolation;
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// De-duplicates, groups, and sorts imports based on the provided `isort` settings.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Consistency is good. Use a common convention for imports to make your code
|
||||||
|
/// more readable and idiomatic.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// import pandas
|
||||||
|
/// import numpy as np
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// import numpy as np
|
||||||
|
/// import pandas
|
||||||
|
/// ```
|
||||||
pub struct UnsortedImports;
|
pub struct UnsortedImports;
|
||||||
);
|
);
|
||||||
impl AlwaysAutofixableViolation for UnsortedImports {
|
impl AlwaysAutofixableViolation for UnsortedImports {
|
||||||
|
|
|
@ -7,6 +7,43 @@ use crate::source_code::Locator;
|
||||||
use crate::violation::Violation;
|
use crate::violation::Violation;
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks for functions with a high `McCabe` complexity.
|
||||||
|
///
|
||||||
|
/// The `McCabe` complexity of a function is a measure of the complexity of the
|
||||||
|
/// control flow graph of the function. It is calculated by adding one to the
|
||||||
|
/// number of decision points in the function. A decision point is a place in
|
||||||
|
/// the code where the program has a choice of two or more paths to follow.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Functions with a high complexity are hard to understand and maintain.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```python
|
||||||
|
/// def foo(a, b, c):
|
||||||
|
/// if a:
|
||||||
|
/// if b:
|
||||||
|
/// if c:
|
||||||
|
/// return 1
|
||||||
|
/// else:
|
||||||
|
/// return 2
|
||||||
|
/// else:
|
||||||
|
/// return 3
|
||||||
|
/// else:
|
||||||
|
/// return 4
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// def foo(a, b, c):
|
||||||
|
/// if not a:
|
||||||
|
/// return 4
|
||||||
|
/// if not b:
|
||||||
|
/// return 3
|
||||||
|
/// if not c:
|
||||||
|
/// return 2
|
||||||
|
/// return 1
|
||||||
|
/// ```
|
||||||
pub struct FunctionIsTooComplex {
|
pub struct FunctionIsTooComplex {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub complexity: usize,
|
pub complexity: usize,
|
||||||
|
|
|
@ -30,20 +30,13 @@ impl Parse for LintMeta {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
let attrs = input.call(Attribute::parse_outer)?;
|
let attrs = input.call(Attribute::parse_outer)?;
|
||||||
|
|
||||||
let mut in_code = false;
|
|
||||||
let mut explanation = String::new();
|
let mut explanation = String::new();
|
||||||
for attr in &attrs {
|
for attr in &attrs {
|
||||||
if let Some(lit) = parse_attr(["doc"], attr) {
|
if let Some(lit) = parse_attr(["doc"], attr) {
|
||||||
let value = lit.value();
|
let value = lit.value();
|
||||||
let line = value.strip_prefix(' ').unwrap_or(&value);
|
let line = value.strip_prefix(' ').unwrap_or(&value);
|
||||||
if line.starts_with("```") {
|
explanation.push_str(line);
|
||||||
explanation += line;
|
explanation.push('\n');
|
||||||
explanation.push('\n');
|
|
||||||
in_code = !in_code;
|
|
||||||
} else if !(in_code && line.starts_with("# ")) {
|
|
||||||
explanation += line;
|
|
||||||
explanation.push('\n');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::new_spanned(attr, "unexpected attribute"));
|
return Err(Error::new_spanned(attr, "unexpected attribute"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,5 @@ It should be removed.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```python
|
```python
|
||||||
|
# print('foo')
|
||||||
```
|
```
|
23
docs/rules/dynamically-typed-expression.md
Normal file
23
docs/rules/dynamically-typed-expression.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# dynamically-typed-expression (ANN401)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that an expression is annotated with a more specific type than `Any`.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
`Any` is a type that can be anything, and it is the default type for
|
||||||
|
unannotated expressions. It is better to be explicit about the type of an
|
||||||
|
expression, and to use `Any` only when it is really needed.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
def foo(x: Any):
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
def foo(x: int):
|
||||||
|
...
|
||||||
|
```
|
41
docs/rules/function-is-too-complex.md
Normal file
41
docs/rules/function-is-too-complex.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# function-is-too-complex (C901)
|
||||||
|
|
||||||
|
Derived from the **mccabe** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks for functions with a high `McCabe` complexity.
|
||||||
|
|
||||||
|
The `McCabe` complexity of a function is a measure of the complexity of the
|
||||||
|
control flow graph of the function. It is calculated by adding one to the
|
||||||
|
number of decision points in the function. A decision point is a place in
|
||||||
|
the code where the program has a choice of two or more paths to follow.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Functions with a high complexity are hard to understand and maintain.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
def foo(a, b, c):
|
||||||
|
if a:
|
||||||
|
if b:
|
||||||
|
if c:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 2
|
||||||
|
else:
|
||||||
|
return 3
|
||||||
|
else:
|
||||||
|
return 4
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
def foo(a, b, c):
|
||||||
|
if not a:
|
||||||
|
return 4
|
||||||
|
if not b:
|
||||||
|
return 3
|
||||||
|
if not c:
|
||||||
|
return 2
|
||||||
|
return 1
|
||||||
|
```
|
26
docs/rules/missing-required-import.md
Normal file
26
docs/rules/missing-required-import.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# missing-required-import (I002)
|
||||||
|
|
||||||
|
Derived from the **isort** linter.
|
||||||
|
|
||||||
|
Autofix is always available.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Adds any required imports, as specified by the user, to the top of the file.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
In some projects, certain imports are required to be present in all files. For
|
||||||
|
example, some projects assume that `from __future__ import annotations` is enabled,
|
||||||
|
and thus require that import to be present in all files. Omitting a "required" import
|
||||||
|
(as specified by the user) can cause errors or unexpected behavior.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
import typing
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import typing
|
||||||
|
```
|
27
docs/rules/missing-return-type-class-method.md
Normal file
27
docs/rules/missing-return-type-class-method.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# missing-return-type-class-method (ANN206)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that class methods have return type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the return types of functions. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any returned values, and the types expected by callers, match expectation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
@classmethod
|
||||||
|
def bar(cls):
|
||||||
|
return 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
@classmethod
|
||||||
|
def bar(cls) -> int:
|
||||||
|
return 1
|
||||||
|
```
|
23
docs/rules/missing-return-type-private-function.md
Normal file
23
docs/rules/missing-return-type-private-function.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# missing-return-type-private-function (ANN202)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that private functions and methods have return type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the return types of functions. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any returned values, and the types expected by callers, match expectation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
def _add(a, b):
|
||||||
|
return a + b
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
def _add(a: int, b: int) -> int:
|
||||||
|
return a + b
|
||||||
|
```
|
23
docs/rules/missing-return-type-public-function.md
Normal file
23
docs/rules/missing-return-type-public-function.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# missing-return-type-public-function (ANN201)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that public functions and methods have return type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the return types of functions. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any returned values, and the types expected by callers, match expectation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
def add(a, b):
|
||||||
|
return a + b
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
return a + b
|
||||||
|
```
|
38
docs/rules/missing-return-type-special-method.md
Normal file
38
docs/rules/missing-return-type-special-method.md
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# missing-return-type-special-method (ANN204)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
Autofix is always available.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that "special" methods, like `__init__`, `__new__`, and `__call__`, have
|
||||||
|
return type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the return types of functions. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any returned values, and the types expected by callers, match expectation.
|
||||||
|
|
||||||
|
Note that type checkers often allow you to omit the return type annotation for
|
||||||
|
`__init__` methods, as long as at least one argument has a type annotation. To
|
||||||
|
opt-in to this behavior, use the `mypy-init-return` setting in your `pyproject.toml`
|
||||||
|
or `ruff.toml` file:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff.flake8-annotations]
|
||||||
|
mypy-init-return = true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
def __init__(self, x: int):
|
||||||
|
self.x = x
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
def __init__(self, x: int) -> None:
|
||||||
|
self.x = x
|
||||||
|
```
|
27
docs/rules/missing-return-type-static-method.md
Normal file
27
docs/rules/missing-return-type-static-method.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# missing-return-type-static-method (ANN205)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that static methods have return type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the return types of functions. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any returned values, and the types expected by callers, match expectation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
@staticmethod
|
||||||
|
def bar():
|
||||||
|
return 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
@staticmethod
|
||||||
|
def bar() -> int:
|
||||||
|
return 1
|
||||||
|
```
|
23
docs/rules/missing-type-args.md
Normal file
23
docs/rules/missing-type-args.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# missing-type-args (ANN002)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that function `*args` arguments have type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any provided arguments match expectation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
def foo(*args):
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
def foo(*args: int):
|
||||||
|
...
|
||||||
|
```
|
30
docs/rules/missing-type-cls.md
Normal file
30
docs/rules/missing-type-cls.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# missing-type-cls (ANN102)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that class method `cls` arguments have type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any provided arguments match expectation.
|
||||||
|
|
||||||
|
Note that many type checkers will infer the type of `cls` automatically, so this
|
||||||
|
annotation is not strictly necessary.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
@classmethod
|
||||||
|
def bar(cls):
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
@classmethod
|
||||||
|
def bar(cls: Type["Foo"]):
|
||||||
|
...
|
||||||
|
```
|
23
docs/rules/missing-type-function-argument.md
Normal file
23
docs/rules/missing-type-function-argument.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# missing-type-function-argument (ANN001)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that function arguments have type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any provided arguments match expectation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
def foo(x):
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
def foo(x: int):
|
||||||
|
...
|
||||||
|
```
|
23
docs/rules/missing-type-kwargs.md
Normal file
23
docs/rules/missing-type-kwargs.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# missing-type-kwargs (ANN003)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that function `**kwargs` arguments have type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any provided arguments match expectation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
def foo(**kwargs):
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
def foo(**kwargs: int):
|
||||||
|
...
|
||||||
|
```
|
28
docs/rules/missing-type-self.md
Normal file
28
docs/rules/missing-type-self.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# missing-type-self (ANN101)
|
||||||
|
|
||||||
|
Derived from the **flake8-annotations** linter.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks that instance method `self` arguments have type annotations.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Type annotations are a good way to document the types of function arguments. They also
|
||||||
|
help catch bugs, when used alongside a type checker, by ensuring that the types of
|
||||||
|
any provided arguments match expectation.
|
||||||
|
|
||||||
|
Note that many type checkers will infer the type of `self` automatically, so this
|
||||||
|
annotation is not strictly necessary.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
def bar(self):
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
class Foo:
|
||||||
|
def bar(self: "Foo"):
|
||||||
|
...
|
||||||
|
```
|
24
docs/rules/unsorted-imports.md
Normal file
24
docs/rules/unsorted-imports.md
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# unsorted-imports (I001)
|
||||||
|
|
||||||
|
Derived from the **isort** linter.
|
||||||
|
|
||||||
|
Autofix is always available.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
De-duplicates, groups, and sorts imports based on the provided `isort` settings.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Consistency is good. Use a common convention for imports to make your code
|
||||||
|
more readable and idiomatic.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```python
|
||||||
|
import pandas
|
||||||
|
import numpy as np
|
||||||
|
```
|
||||||
|
|
||||||
|
Use instead:
|
||||||
|
```python
|
||||||
|
import numpy as np
|
||||||
|
import pandas
|
||||||
|
```
|
Loading…
Add table
Add a link
Reference in a new issue