mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00
Allow flake8-type-checking
rules to automatically quote runtime-evaluated references (#6001)
## Summary This allows us to fix usages like: ```python from pandas import DataFrame def baz() -> DataFrame: ... ``` By quoting the `DataFrame` in `-> DataFrame`. Without quotes, moving `from pandas import DataFrame` into an `if TYPE_CHECKING:` block will fail at runtime, since Python tries to evaluate the annotation to add it to the function's `__annotations__`. Unfortunately, this does require us to split our "annotation kind" flags into three categories, rather than two: - `typing-only`: The annotation is only evaluated at type-checking-time. - `runtime-evaluated`: Python will evaluate the annotation at runtime (like above) -- but we're willing to quote it. - `runtime-required`: Python will evaluate the annotation at runtime (like above), and some library (like Pydantic) needs it to be available at runtime, so we _can't_ quote it. This functionality is gated behind a setting (`flake8-type-checking.quote-annotations`). Closes https://github.com/astral-sh/ruff/issues/5559.
This commit is contained in:
parent
4d2ee5bf98
commit
1a65e544c5
18 changed files with 1034 additions and 208 deletions
|
@ -1642,6 +1642,57 @@ pub struct Flake8TypeCheckingOptions {
|
|||
"#
|
||||
)]
|
||||
pub runtime_evaluated_decorators: Option<Vec<String>>,
|
||||
|
||||
/// Whether to add quotes around type annotations, if doing so would allow
|
||||
/// the corresponding import to be moved into a type-checking block.
|
||||
///
|
||||
/// For example, in the following, Python requires that `Sequence` be
|
||||
/// available at runtime, despite the fact that it's only used in a type
|
||||
/// annotation:
|
||||
///
|
||||
/// ```python
|
||||
/// from collections.abc import Sequence
|
||||
///
|
||||
///
|
||||
/// def func(value: Sequence[int]) -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// In other words, moving `from collections.abc import Sequence` into an
|
||||
/// `if TYPE_CHECKING:` block above would cause a runtime error, as the
|
||||
/// type would no longer be available at runtime.
|
||||
///
|
||||
/// By default, Ruff will respect such runtime semantics and avoid moving
|
||||
/// the import to prevent such runtime errors.
|
||||
///
|
||||
/// Setting `quote-annotations` to `true` will instruct Ruff to add quotes
|
||||
/// around the annotation (e.g., `"Sequence[int]"`), which in turn enables
|
||||
/// Ruff to move the import into an `if TYPE_CHECKING:` block, like so:
|
||||
///
|
||||
/// ```python
|
||||
/// from typing import TYPE_CHECKING
|
||||
///
|
||||
/// if TYPE_CHECKING:
|
||||
/// from collections.abc import Sequence
|
||||
///
|
||||
///
|
||||
/// def func(value: "Sequence[int]") -> None:
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// Note that this setting has no effect when `from __future__ import annotations`
|
||||
/// is present, as `__future__` annotations are always treated equivalently
|
||||
/// to quoted annotations.
|
||||
#[option(
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
# Add quotes around type annotations, if doing so would allow
|
||||
# an import to be moved into a type-checking block.
|
||||
quote-annotations = true
|
||||
"#
|
||||
)]
|
||||
pub quote_annotations: Option<bool>,
|
||||
}
|
||||
|
||||
impl Flake8TypeCheckingOptions {
|
||||
|
@ -1651,8 +1702,9 @@ impl Flake8TypeCheckingOptions {
|
|||
exempt_modules: self
|
||||
.exempt_modules
|
||||
.unwrap_or_else(|| vec!["typing".to_string()]),
|
||||
runtime_evaluated_base_classes: self.runtime_evaluated_base_classes.unwrap_or_default(),
|
||||
runtime_evaluated_decorators: self.runtime_evaluated_decorators.unwrap_or_default(),
|
||||
runtime_required_base_classes: self.runtime_evaluated_base_classes.unwrap_or_default(),
|
||||
runtime_required_decorators: self.runtime_evaluated_decorators.unwrap_or_default(),
|
||||
quote_annotations: self.quote_annotations.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue