From 7479dfd8153b1a4a30e3b2cdbcb685ef3a9e2281 Mon Sep 17 00:00:00 2001 From: Tom Kuson Date: Wed, 24 May 2023 01:45:32 +0100 Subject: [PATCH] Add Pyflakes docs (#4588) --- .../ruff/src/rules/pyflakes/rules/imports.rs | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/crates/ruff/src/rules/pyflakes/rules/imports.rs b/crates/ruff/src/rules/pyflakes/rules/imports.rs index a0dcae819e..373beefc6b 100644 --- a/crates/ruff/src/rules/pyflakes/rules/imports.rs +++ b/crates/ruff/src/rules/pyflakes/rules/imports.rs @@ -15,6 +15,44 @@ pub(crate) enum UnusedImportContext { Init, } +/// ## What it does +/// Checks for unused imports. +/// +/// ## Why is this bad? +/// Unused imports add a performance overhead at runtime, and risk creating +/// import cycles. They also increase the cognitive load of reading the code. +/// +/// If an import statement is used to check for the availability or existence +/// of a module, consider using `importlib.util.find_spec` instead. +/// +/// ## Example +/// ```python +/// import numpy as np # unused import +/// +/// +/// def area(radius): +/// return 3.14 * radius**2 +/// ``` +/// +/// Use instead: +/// ```python +/// def area(radius): +/// return 3.14 * radius**2 +/// ``` +/// +/// To check the availability of a module, use `importlib.util.find_spec`: +/// ```python +/// from importlib.util import find_spec +/// +/// if find_spec("numpy") is not None: +/// print("numpy is installed") +/// else: +/// print("numpy is not installed") +/// ``` +/// +/// ## References +/// - [Python documentation](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement) +/// - [Python documentation](https://docs.python.org/3/library/importlib.html#importlib.util.find_spec) #[violation] pub struct UnusedImport { pub(crate) name: String, @@ -54,6 +92,34 @@ impl Violation for UnusedImport { }) } } + +/// ## What it does +/// Checks for import bindings that are shadowed by loop variables. +/// +/// ## Why is this bad? +/// Shadowing an import with loop variables makes the code harder to read and +/// reason about, as the identify of the imported binding is no longer clear. +/// It's also often indicative of a mistake, as it's unlikely that the loop +/// variable is intended to be used as the imported binding. +/// +/// Consider using a different name for the loop variable. +/// +/// ## Example +/// ```python +/// from os import path +/// +/// for path in files: +/// print(path) +/// ``` +/// +/// Use instead: +/// ```python +/// from os import path +/// +/// +/// for filename in files: +/// print(filename) +/// ``` #[violation] pub struct ImportShadowedByLoopVar { pub(crate) name: String, @@ -68,6 +134,34 @@ impl Violation for ImportShadowedByLoopVar { } } +/// ## What it does +/// Checks for the use of wildcard imports. +/// +/// ## Why is this bad? +/// Wildcard imports (e.g., `from module import *`) make it hard to determine +/// which symbols are available in the current namespace, and from which module +/// they were imported. +/// +/// ## Example +/// ```python +/// from math import * +/// +/// +/// def area(radius): +/// return pi * radius**2 +/// ``` +/// +/// Use instead: +/// ```python +/// from math import pi +/// +/// +/// def area(radius): +/// return pi * radius**2 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#imports) #[violation] pub struct UndefinedLocalWithImportStar { pub(crate) name: String, @@ -81,6 +175,31 @@ impl Violation for UndefinedLocalWithImportStar { } } +/// ## What it does +/// Checks for `__future__` imports that are not located at the beginning of a +/// file. +/// +/// ## Why is this bad? +/// Imports from `__future__` must be placed the beginning of the file, before any +/// other statements (apart from docstrings). The use of `__future__` imports +/// elsewhere is invalid and will result in a `SyntaxError`. +/// +/// ## Example +/// ```python +/// from pathlib import Path +/// +/// from __future__ import annotations +/// ``` +/// +/// Use instead: +/// ```python +/// from __future__ import annotations +/// +/// from pathlib import Path +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#module-level-dunder-names) #[violation] pub struct LateFutureImport; @@ -91,6 +210,43 @@ impl Violation for LateFutureImport { } } +/// ## What it does +/// Checks for names that might be undefined, but may also be defined in a +/// wildcard import. +/// +/// ## Why is this bad? +/// Wildcard imports (e.g., `from module import *`) make it hard to determine +/// which symbols are available in the current namespace. If a module contains +/// a wildcard import, and a name in the current namespace has not been +/// explicitly defined or imported, then it's unclear whether the name is +/// undefined or was imported by the wildcard import. +/// +/// If the name _is_ defined in via a wildcard import, that member should be +/// imported explicitly to avoid confusion. +/// +/// If the name is _not_ defined in a wildcard import, it should be defined or +/// imported. +/// +/// ## Example +/// ```python +/// from math import * +/// +/// +/// def area(radius): +/// return pi * radius**2 +/// ``` +/// +/// Use instead: +/// ```python +/// from math import pi +/// +/// +/// def area(radius): +/// return pi * radius**2 +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#imports) #[violation] pub struct UndefinedLocalWithImportStarUsage { pub(crate) name: String, @@ -109,6 +265,33 @@ impl Violation for UndefinedLocalWithImportStarUsage { } } +/// ## What it does +/// Check for the use of wildcard imports outside of the module namespace. +/// +/// ## Why is this bad? +/// The use of wildcard imports outside of the module namespace (e.g., within +/// functions) can lead to confusion, as the import can shadow local variables. +/// +/// Though wildcard imports are discouraged, when necessary, they should be placed +/// in the module namespace (i.e., at the top-level of a module). +/// +/// ## Example +/// ```python +/// def foo(): +/// from math import * +/// ``` +/// +/// Use instead: +/// ```python +/// from math import * +/// +/// +/// def foo(): +/// ... +/// ``` +/// +/// ## References +/// - [PEP 8](https://peps.python.org/pep-0008/#imports) #[violation] pub struct UndefinedLocalWithNestedImportStarUsage { pub(crate) name: String, @@ -122,6 +305,16 @@ impl Violation for UndefinedLocalWithNestedImportStarUsage { } } +/// ## What it does +/// Checks for `__future__` imports that are not defined in the current Python +/// version. +/// +/// ## Why is this bad? +/// Importing undefined or unsupported members from the `__future__` module is +/// a `SyntaxError`. +/// +/// ## References +/// - [Python documentation](https://docs.python.org/3/library/__future__.html) #[violation] pub struct FutureFeatureNotDefined { name: String,